# Billing plans that control what the product can actually do

> Build SaaS pricing around real plans, subscriptions, feature entitlements, usage limits, provider-specific price records, and an admin control surface.

Source: https://saascode.ai/inside/billing-saas-plans-feature-gating · Published: 2026-08-21 · Section: fabric

---
A SaaS billing starter is not finished when it can draw three pricing cards. Billing has to connect a price to a plan, a plan to an organization, and that organization to the features the product will allow. The included billing layer carries that connection from the database to the admin panel and into runtime feature checks.

The plan model supports free, recurring, and one-time billing types. A plan can store its price, currency, billing interval, interval count, trial days, display features, structured limits, active state, recommendation state, and display order. Organizations point to plans, while the subscriptions table records the plan and lifecycle state for each organization.

That gives pricing a real data model. The public plans endpoint returns active plan data for pricing surfaces. The admin endpoints create and edit the same records. There is no separate hardcoded pricing array that has to be kept in sync with the thing billing logic reads.

## Entitlements live beside pricing

Feature flags are organization-scoped records. Each one has an enabled state and an optional list of plan IDs that may use it. When the list is empty, the enabled flag is enough. When the list contains plans, the runtime checks the organization's plan before granting access.

The base exposes that check in three useful forms. Server code can ask whether a feature is enabled for an organization. Client code can use the same rule to render a gated interface. An API endpoint can answer a direct feature check. Missing flags and database errors use a default-deny path in the server helper, so an absent entitlement does not silently become access.

The admin plan route keeps the relationship synchronized. When an owner chooses which features a plan includes, the route adds or removes that plan's UUID from each feature flag's `requires_plan` list. Deleting a plan also removes stale references from those lists. The model is simple enough to inspect in Postgres and useful enough to control real product behavior.

Per-organization overrides sit on top. The organization detail area can toggle a feature for one tenant and store limit overrides for that tenant. That covers the common cases where a customer needs an exception without forcing the owner to invent another public plan.

## Pricing stays independent from the payment rail

Plans are provider-agnostic. The plan keeps business-facing price data. A separate `provider_prices` table stores the external product and price identifiers for each payment provider, plus synchronization status and errors. The checkout endpoint asks which provider-price rows are actually ready before offering a payment option.

This separation matters when a product supports more than one processor. Stripe, PayPal, Paddle, and a regional gateway do not use the same remote IDs or product APIs. The internal plan can remain “Pro” while each processor gets its own price record.

The provider adapters declare their capabilities. All 18 current payment adapters support one-time checkout. Fifteen declare subscription support. Seven can create remote products and prices through their APIs. The admin price-sync route checks those capabilities instead of assuming every processor can do the same work.

## What the owner sees

The admin plans API returns subscriber counts, feature flags, and provider-price records beside each plan. Creating a plan accepts its billing type, price, currency, interval, trial, display copy, feature access, and limits. Editing uses the same model. A free plan forces its price to zero. Plans can also be reordered for the public pricing surface.

The public plan response intentionally uses the human-authored display-feature list for the pricing card. Access control comes from feature flags, not from parsing marketing copy. That avoids a fragile class of bugs where changing a bullet point accidentally changes an entitlement.

This is the right split for a buyer: pricing copy remains copy; feature access remains structured data; payment-provider IDs remain integration data.

## The honest limit

The `limits` field is storage, not universal enforcement. The base gives plans and organization overrides a place to define numeric limits, but product-specific actions still have to check the relevant limit when they create a record, consume credits, upload a file, or run some other metered operation. Feature gates are wired generically. Every possible usage counter cannot be, because each product has different things to count.

Remote price creation is not uniform either. Eleven of the 18 adapters do not declare product-creation support, even though they can process checkout with a configured external price. Those providers need a manually created price ID or provider-specific setup. A customer portal is also a provider capability, not a universal billing feature.

The layer does not turn plan design into an accounting system. It models plans, subscriptions, entitlements, limits, and external price references. Tax rules, bookkeeping, and the commercial decision about what each tier should include remain outside that model.

## Why billing belongs in the base

Billing decisions change. A product may launch with one free plan, add a recurring plan, test a one-time offer, or switch its payment mix for a new region. If pricing, entitlements, and processor IDs are hardcoded together, each change becomes a code migration.

The included structure keeps those concerns separate and connected. The owner manages pricing and feature access from the admin. The product checks entitlements at runtime. Payment adapters attach their own identifiers without rewriting the plan. Tenant exceptions remain possible without multiplying public tiers.

Every product needs that floor even when the first release is free. The free plan is still a plan. Feature access still needs a source of truth. The organization still needs a place to point when paid tiers arrive. Starting with the full relationship keeps the first billing change from becoming a rebuild.
