SaaS Subscription Billing Architecture: Plans, Access, and Payment Events
Plan SaaS subscription billing around entitlements, subscription states, webhooks, usage measurement, plan changes, and reconciliation.
Subscription billing connects pricing, access rules, invoices, and payment events. Define failed-payment handling, plan changes, cancellation, and reconciliation alongside the initial checkout flow.
Why SaaS Subscription Billing Deserves Architectural Attention
The initial checkout flow is only one path: a user selects a plan, enters a payment method, and starts a subscription.
The unhappy paths are where architecture matters:
- What happens when a payment fails mid-billing period?
- How does proration work when a user upgrades from annual to monthly mid-cycle?
- What happens if a user's subscription lapses and they attempt to access gated features?
- How does a team downgrade from fifty seats to five, and what does the charge look like?
- What does your data model look like when you add a usage-based tier to a previously flat-rate product?
Each of these is a product decision, a data modeling decision, and a Stripe integration decision simultaneously. Getting them wrong means incorrect charges, customer support escalations, and revenue leakage.
The Core Design Decisions in SaaS Subscription Billing Architecture
Plan and Entitlement Modeling
The first decision is whether your plan model lives primarily in Stripe or primarily in your own database.
Stripe-native plan modeling means your plan structure, pricing, and features are defined in Stripe's product and price objects. Your application reads plan metadata from Stripe to determine feature access. This reduces duplication but creates a dependency on Stripe's data model being able to express your plan structure.
Database-native plan modeling means your application maintains its own plan definitions, feature flags, and entitlement rules. Stripe is a payment processor, not a source of truth for what a customer is allowed to do. This is more flexible but requires keeping your plan model and Stripe's billing configuration synchronized.
One option is a hybrid approach: Stripe handles billing mechanics (subscription lifecycle, charge schedules, invoicing), while your application's database is the source of truth for what each subscription tier allows.
The Subscription State Machine
A subscription is not binary. The states a subscription passes through require explicit handling in your application:
trialing— user has not yet been charged, may have access to full or limited featuresactive— payment is current, full accesspast_due— payment failed, Stripe is retrying, access policy is a product decisioncanceled— subscription ended, access should be revoked at period endincomplete— initial payment failed before subscription activated
Your access control logic must handle each state. One state to define explicitly is past_due. When a payment fails, does the user lose access immediately? After a grace period? After the second retry? These are product decisions that need to be made explicitly, documented, and implemented — not discovered when a customer complains.
Webhook Architecture
Stripe communicates subscription state changes via webhooks. Your application's billing state is only as accurate as your webhook handling is reliable.
Critical design requirements for webhook handling:
- Idempotent processing — webhooks can be delivered more than once. Your handlers must produce the same result regardless of how many times they process the same event.
- Delivery verification — verify Stripe's webhook signature on every incoming request before processing.
- Durable queue — do not process webhooks synchronously in the request handler. Enqueue them and process asynchronously so that downstream failures (database errors, email delivery issues) do not prevent acknowledgment to Stripe.
- Observability — log every webhook received, every event type processed, and every failure. Billing bugs are much easier to diagnose with a complete event log.
Metered and Usage-Based Billing
Flat-rate billing is straightforward. Usage-based billing — where charges depend on API calls, seats, storage consumed, or transactions processed — adds measurement, aggregation, and billing period reconciliation to the architecture.
If metered billing is in your roadmap (even if it is not in your MVP), design the event tracking infrastructure to support it before the flat-rate product ships. Retroactively adding usage measurement to a product that was not built for it is significantly more complex than building it in from the start.
Proration and Upgrade/Downgrade Flows
Stripe handles proration calculation for mid-cycle plan changes, but your application controls when and how those changes are presented to the user. Decisions to make explicitly:
- Are upgrades effective immediately or at period end?
- Are downgrades effective immediately or at period end?
- How is proration communicated to the user before they confirm the change?
Leaving these as implicit defaults creates confusion for users who see unexpected charges and unexpected access changes.
Revenue Reconciliation
Stripe's dashboard is not your accounting system. Build or integrate a process for reconciling Stripe revenue against your internal subscription records on a regular cadence. Discrepancies between what Stripe says customers were charged and what your application believes their subscription state is are a real phenomenon — and they are much easier to resolve when discovered weekly than when discovered at end of year during financial audit.
Document access rules and reconcile provider events with application state. Test billing changes against those rules before release.
For help defining subscription states and billing flows, contact LinkIT.