DEV Community

Cover image for Our Portfolio Runs on One-Time Payments. Here's the Stripe Setup.
Jakub
Jakub

Posted on

Our Portfolio Runs on One-Time Payments. Here's the Stripe Setup.

Every SaaS playbook says the same thing: build recurring revenue. MRR is king. Subscriptions scale.

I went the other way. Our portfolio of 14 products runs entirely on one-time payments. No monthly fees, no annual plans, no "cancel anytime" copy. You pay once, you get your thing, done.

Here's why, and how we set it up with Stripe.

The subscription fatigue problem

People are tired. The average consumer now manages 12+ active subscriptions. Every new tool wants $9/month, $29/month, $99/month. And for products people use once or twice? That math just doesn't work for either side.

We build AI-powered tools. Most of our users come in, do one thing, and leave happy. An animated photo. A custom song. A code audit report. Charging $9/month for something someone uses once a quarter felt dishonest.

So we asked: what if we just... didn't?

What our payment model looks like

Three products, three simple prices:

  • Magical Song - AI-generated custom songs with real vocals. $6 per song. No account needed.
  • Audit Vibecoding - Professional audit of AI-generated code. $4-9 per report. 47 checks across security, SEO, performance, accessibility.
  • Ziva Fotka - AI photo animation. One-time payment per animation. Serves 5 markets (CZ, SK, PL, EN, DE) from a single codebase.

No free trials that convert to paid. No credit card upfront. No dark patterns. You see the price, you pay, you get value. Immediately.

The Stripe implementation

Setting up one-time payments with Stripe is surprisingly simple. Here's the architecture we use across all products:

User clicks "Buy" > Stripe Checkout Session (server-side) > Payment > Webhook > Deliver value
Enter fullscreen mode Exit fullscreen mode

The key piece is Stripe Checkout in payment mode (not subscription):

const session = await stripe.checkout.sessions.create({
  mode: 'payment',
  line_items: [{
    price_data: {
      currency: 'usd',
      product_data: {
        name: 'Custom AI Song',
        description: 'Studio-quality song with real vocals',
      },
      unit_amount: 600, // $6.00
    },
    quantity: 1,
  }],
  success_url: YOUR_DOMAIN + '/success?session_id={CHECKOUT_SESSION_ID}',
  cancel_url: YOUR_DOMAIN + '/cancel',
});
Enter fullscreen mode Exit fullscreen mode

Then handle the webhook:

// Listen for checkout.session.completed
app.post('/webhook', async (req, res) => {
  const event = stripe.webhooks.constructEvent(
    req.body,
    req.headers['stripe-signature'],
    webhookSecret
  );

  if (event.type === 'checkout.session.completed') {
    const session = event.data.object;
    // Trigger value delivery (generate song, run audit, etc.)
    await deliverProduct(session.metadata.productType, session);
  }

  res.json({ received: true });
});
Enter fullscreen mode Exit fullscreen mode

That's it. No subscription logic, no billing cycles, no failed payment retry flows, no churn tracking infrastructure. The simplicity is the point.

What we learned

Conversion rates are higher than we expected. When someone sees "$6, one time" vs "$9/month", the barrier drops significantly. People don't need to calculate annual cost or worry about forgetting to cancel.

Support load dropped. No "how do I cancel?" emails. No "I was charged again" disputes. No proration questions. Our support inbox is mostly "cool product, thanks."

The economics work differently. Yes, we don't get monthly compounding. But we also don't have churn. Every dollar earned is earned. No MRR anxiety, no cohort decay charts to stare at.

Multi-currency is free complexity. Stripe handles it. We set prices in USD and Stripe converts automatically based on the buyer's card. For Ziva Fotka, which runs across 5 countries, this was a huge win.

When one-time payments DON'T work

I'm not saying subscriptions are bad. They make sense when:

  • Your product delivers ongoing value (project management, communication)
  • Users come back daily or weekly
  • You need to fund continuous infrastructure costs per user

But if your product is transactional, if users come for a specific output, one-time payments align incentives better. You only get paid when you deliver value. There's something clean about that.

The tech stack

All our products run on React + Supabase + Stripe, deployed through Lovable. The payment flow is identical across products, just with different prices and delivery logic. We built it once and reuse it everywhere.

If you're building something where users want a result, not a relationship, consider skipping the subscription. Your Stripe integration will be simpler, your users will be happier, and you might be surprised by the conversion numbers.


Building 14 products in public at inithouse.com. Follow the journey.

Top comments (0)