How do you implement Stripe billing in a SaaS app?
You implement Stripe billing in a SaaS app by modeling your plans as Stripe products and prices, sending customers to Checkout to subscribe, listening to webhooks to keep your database in sync, and checking a local entitlements record before enabling any feature. Stripe handles cards, invoices and retries; your app handles access.
This is the engineering side of billing. The design side, from plan pages to paywalls and usage limits, is in our guide to in-app billing and upgrade UX, and the two should be planned together. Both are part of our hub on full-stack product engineering for startups.
Model plans and prices
Create a product per plan and a price per billing interval and currency. Store Stripe price IDs in config, not scattered through code.
Link customers to workspaces
Create one Stripe customer per workspace or organization and store its ID on the workspace record.
Subscribe through Checkout
Create a Checkout Session on the server for the chosen price and redirect the user. Stripe handles payment details, tax collection options and authentication.
Sync with webhooks
Handle subscription and invoice events to update your local subscription and entitlements records.
Gate features locally
Every feature check reads your own entitlements record, never the Stripe API on each request.
Hand off self-service
Link to the Stripe Customer Portal so customers can change plans, update cards and download invoices.
How should you model plans, prices and entitlements?
Model each plan as a Stripe product with one price per interval, such as monthly and annual, and keep a separate entitlements map in your code that says what each plan includes. Separating price from permission lets you change prices, run discounts or grandfather old customers without touching feature checks.
Concept | Lives in | Example |
|---|---|---|
Product | Stripe | Pro plan |
Price | Stripe | Pro, billed monthly, in USD |
Subscription | Stripe, mirrored locally | Workspace X on Pro, renews next month |
Entitlements | Your database | Up to N seats, API access on, SSO off |
Usage | Your database, reported to Stripe if metered | Reports generated this period |
Stripe also offers its own entitlements feature that maps products to features. It's worth evaluating, but keep a local copy either way, because your app needs to answer "can this workspace do X" instantly, even if Stripe is slow to respond.
Which Stripe webhooks does a SaaS app need?
A SaaS app needs webhooks for the moments a subscription starts, changes, renews, fails or ends. At minimum, handle a completed Checkout Session, subscription created, updated and deleted events, and invoice paid and payment failed events. Those cover most of the subscription lifecycle.
- Checkout completed: link the new subscription to the workspace that started it.
- Subscription created or updated: store the plan, status, period end, trial end and cancellation flag, then recompute entitlements.
- Subscription deleted: move the workspace to the free tier or a locked state.
- Invoice paid: confirm the renewal and clear any past-due warning.
- Invoice payment failed: flag the workspace as past due and start your in-app and email reminders.
Writing webhook handlers that don't break
Verify every webhook's signature with your endpoint secret before reading it, and reject anything that fails.
Make handlers idempotent: Stripe can send the same event more than once, and events can arrive out of order. Store processed event IDs, and when an event concerns a subscription, fetch the subscription's current state from Stripe and save that, rather than applying the event as a delta.
Respond quickly with a success status and move slow work, such as sending emails or recalculating usage, to a background job. Test with the Stripe CLI, which can forward events to your local machine and trigger test events on demand.
How should SaaS trials work with Stripe subscriptions?
SaaS trials in Stripe work by creating a subscription with a trial period, with or without collecting a payment method up front. Card-required trials convert differently from card-free trials, so decide based on your sales motion and design the emails and in-app reminders around the trial end.
Pros
- Card-free trial: lower friction, more people start
- Card-free trial: works well for product-led growth with strong activation
- Card-required trial: users who start have shown more intent, and renewal is automatic
Cons
- Card-free trial: needs clear prompts to add a card before the trial ends
- Card-free trial: needs a defined state for trials that end with no payment method
- Card-required trial: fewer people start, and some will dispute charges they forgot about
Whichever you choose, show the trial's end date inside the product, send a reminder before it ends and make cancellation easy. Check the current rules for the regions you sell in, because subscription and cancellation regulations vary.
How do you add metered or usage-based billing?
Add usage-based billing by recording usage events in your own database first, then reporting them to Stripe's meters so invoices reflect actual use. Keeping your own record lets you show live usage in the product, enforce limits and reconcile any disagreement with what Stripe billed.
Most SaaS products do best with a hybrid: a base subscription that includes an allowance, plus usage charges above it. It keeps invoices predictable for buyers while still charging fairly for heavy use. Show usage clearly in a billing section of your settings pages, with warnings before a limit, not only after.
How do you handle failed payments and plan changes?
Handle failed payments with Stripe's automatic retries and reminder emails, plus your own in-app banner for workspace admins, and a defined grace period before you restrict access. Handle plan changes by letting Stripe calculate proration and updating entitlements from the resulting webhook.
Restrict carefully. Locking a whole team out on the first failed payment punishes users who can't fix billing. A softer pattern is a banner for admins, then read-only access, then a lock. Downgrades need equal care: decide what happens to seats, projects or data above the new plan's limits before a customer asks.
What does a reliable Stripe billing architecture look like?
A reliable architecture keeps billing logic in one module: one place creates Checkout Sessions and portal links, one webhook route processes events, and one function answers what a workspace is entitled to. Every other part of the app calls those functions.
Type the whole flow, from Stripe event payloads to your entitlements, as we argue in TypeScript for startups, and keep billing tables in the same Postgres database as your workspaces. The wider structure, including where authorization lives, is in building a SaaS app with Next.js.
