Billing Is Where SaaS Products Go to Die
Not with a dramatic crash. With a slow leak. A customer gets double-charged and loses trust.
An upgrade doesn’t prorate correctly, and finance spends three hours reconciling. A failed payment silently churns a customer who would’ve stayed.
Stripe named a Leader in the 2025 Forrester Wave for Recurring Billing Solutions and the 2025 Gartner Magic Quadrant for good reason. It handles the brutally hard parts: payment retries, tax calculation, invoicing, PCI compliance. Your job is to integrate it correctly.
We’ve built Stripe integrations for multiple SaaS platforms. This is what we wish someone had told us first.
Don’t Build Your Own Billing System
This bears repeating. We’ve watched teams spend six months rebuilding what Stripe gives you out of the box. Subscription lifecycle management, proration, dunning, invoice generation, tax compliance. All of it. Already built.
77% of the largest software companies now use consumption-based pricing through platforms like Stripe. You’re not smarter than Stripe’s billing team. Use their infrastructure, spend your engineering time on your actual product.
If you’re new to SaaS architecture, our complete multi-tenant SaaS guide covers how billing fits into the bigger picture.
The Core Architecture
Your SaaS has two sources of truth for billing: Stripe and your database. They need to stay in sync. Always.
Stripe owns payment state: subscriptions, invoices, payment methods, charges. Your database owns business state: which tenant is on which plan, what features they can access, usage counters.
The bridge between them is webhooks. Stripe fires events for every billing action (subscription created, payment succeeded, invoice finalized). Your webhook handler updates your database accordingly.
Never poll Stripe’s API to check subscription status. That’s fragile and slow. Trust the webhooks.
Webhook Architecture That Won’t Break
Webhooks are the backbone. Get them wrong and your billing state drifts from reality. Here’s how to get them right.
Idempotency first. Stripe can (and will) send the same event multiple times. Your handler must process each event exactly once.
Store the event ID, check before processing.
Process asynchronously. Don’t do heavy work inside the webhook handler. Acknowledge the webhook with a 200 response immediately, then queue the actual processing.
Stripe retries on timeout, and if your handler takes too long, you’ll get duplicate events.
Handle out-of-order events. Stripe doesn’t guarantee delivery order. A subscription.updated event can arrive before subscription.created.
Your handler needs to be resilient to this.
Log everything. Every webhook received, every processing step, every state change. When billing goes wrong (and it will), these logs are the only way to diagnose what happened.
Subscription Lifecycle
The subscription lifecycle has more states than most developers expect.
A customer signs up and enters a trial period (or not). Trial converts to active subscription. Payments succeed or fail.
Failed payments trigger dunning: retry logic and reminder emails. Eventually the subscription is canceled, either by the customer or by exhausted retries.
Each transition fires a Stripe event. Each event needs a handler. Missing even one creates a gap where your system’s understanding of the subscription diverges from reality.
The transitions that trip people up: trial ending without a payment method on file, mid-cycle plan changes that require proration, and the gap between “subscription canceled” and “subscription actually expires at period end.”
Pricing Models
Per-seat pricing still dominates at 57% of SaaS companies, but it’s declining. Usage-based pricing now appears in 43% of models, up from 35% a year ago. Hybrid models are growing fastest, at 61%.
Stripe’s Meters API handles usage-based billing natively. Send usage events in real-time, and Stripe aggregates them for invoicing. No need to build your own metering pipeline.
For seat-based pricing, Stripe’s quantity-based subscriptions work well. Update the quantity when seats are added or removed. Stripe handles proration.
For tiered pricing, define your tiers in Stripe’s product catalog. Each tier maps to a price with specific features and limits. Your application checks the tenant’s active price to determine feature access.
Need help deciding which model fits your product? Our guide on how to price your SaaS product covers the strategic side.
Free Trials That Convert
Self-service trials convert at 15-25% for good products. Two approaches: card upfront or no card required.
Card upfront filters for serious buyers. Conversion rates are higher, but top-of-funnel is smaller. No card required gets more signups, but many will never convert.
We lean toward card upfront for B2B SaaS. The users who enter a card are genuinely evaluating your product. The ones who don’t were browsing.
Stripe handles trial periods natively. Set the trial duration on the subscription, and Stripe won’t charge until it ends. If no payment method is on file when the trial expires, the subscription moves to past_due. Handle that event.
Dunning: The Revenue You’re Leaving on the Table
Failed payments cause involuntary churn. Not because customers want to leave, but because their card expired or hit a limit. Stripe’s Smart Retries use machine learning to retry payments at optimal times. Enable it.
Beyond retries, send dunning emails. A 3-email sequence over 14 days is standard. First email: “your payment failed, please update your card.” Second: “your account will be downgraded in 7 days.” Third: “your account has been downgraded.”
Stripe Billing automates this entire sequence. The amount of revenue recovered from dunning alone can be 5-10% of your MRR. That’s not pocket change.
Upgrades, Downgrades, and Proration
Plan changes need to feel instant to the customer. Click upgrade, get access immediately. The billing details should sort themselves out.
Stripe handles proration automatically. If a customer upgrades mid-cycle, Stripe credits the unused portion of the old plan and charges the prorated amount for the new plan. Your webhook handler updates the tenant’s feature access when the subscription change event arrives.
Downgrades are trickier. We recommend applying downgrades at period end, not immediately. The customer paid for the current period; let them keep the features until renewal.
Connecting Billing to Your Tenant System
Every Stripe customer maps to a tenant in your database. Store the Stripe customer ID on your tenant record. When a webhook arrives, resolve the tenant from the Stripe customer ID and update accordingly.
Feature gating based on subscription tier is your application’s responsibility, not Stripe’s. Your middleware checks the tenant’s plan and enforces limits: API rate limits, storage quotas, user counts, feature flags.
Cache the subscription status. Don’t query Stripe (or even your database) on every request to check plan limits. Cache the tenant’s plan and features in Redis, and invalidate when a webhook updates them.
For how billing integrates with your broader authentication and access control system, see our guide on SaaS authentication: SSO, OAuth, and RBAC.
Testing Billing Without Losing Your Mind
Stripe’s test mode is your friend. Use it for every scenario: successful payments, failed payments, card declines, expired trials, plan changes, refunds. Every path that can happen in production should have a test in your CI pipeline.
Stripe’s test clocks let you simulate time. Fast-forward through trial periods, billing cycles, and dunning sequences without waiting. Worth its weight in gold.
One thing we always do: a full billing integration test that creates a tenant, subscribes them, processes a payment, upgrades them, and cancels. If that flow works end-to-end, you’re in good shape.
Our Billing Checklist
After several Stripe integrations, here’s what we verify before launch.
Webhook endpoint is idempotent and processes async. Every subscription lifecycle event has a handler. Dunning is configured with Smart Retries and email sequences.
Proration handles upgrades and downgrades correctly. Feature access updates within seconds of plan changes. Test coverage includes all payment failure scenarios.
Skip any of these and you’ll find out in production. With real money.
Building a SaaS product and need billing that works from day one? Let’s architect it together. We’ve integrated Stripe for multi-tenant platforms and know where the edge cases hide.