Feature gating by plan: entitlements for SaaS apps
How SaaS developers can gate features and limits by plan with an entitlements model, keep it in sync with billing, and handle trials and downgrades.
- Published
- Reading time
- 5 min read
- By
- CentraPoint Team
On this page
Every SaaS product with more than one plan needs to answer the same question on almost every request: is this customer allowed to do this? The quick answer is to check the plan name in code, as in "if plan is Business, show reports". It works until you add a plan, rename one, run a promotion or give one customer a custom deal. Then plan names are scattered through the code base and every pricing change becomes a deployment.
An entitlements model solves this by separating what a customer has paid for from how your code checks it.
What an entitlement is
An entitlement is a single thing a customer is allowed to have. It comes in two common forms:
- Feature flags: on or off. "Can use the API", "can export to Excel", "has custom branding".
- Limits: a number. "Up to 10 users", "5 API keys", "1,000 SMS per month". A common convention is that no limit means unlimited and zero means not included.
Plans are then just bundles of entitlements. Your code checks entitlements; it never checks plan names.
Design the model
1. List features and limits once
Keep a single definition of every feature key and limit key, with a human-readable label. Use stable keys that won't change when marketing renames a plan.
2. Map plans to entitlements
Each plan sets every feature to on or off and every limit to a number. Store this as data, not code, so that a new plan or a changed limit doesn't need a release.
3. Allow overrides
Sooner or later, a customer needs one extra feature or a higher limit without changing plan. Support per-customer overrides on top of the plan, and record who granted them and why.
4. Resolve once, check everywhere
Work out the customer's effective entitlements (plan plus overrides) in one place, and give the rest of your code a single function such as can(customer, "featExport") or limit(customer, "maxUsers").
Keep entitlements in sync with billing
Entitlements are only correct if they follow the customer's actual subscription. The usual pattern:
- Your billing system is the source of truth for which plan each customer is on and whether it is active, trialling, past due or cancelled.
- Webhooks tell your app when something changes: a new subscription, a plan change, a failed payment, a cancellation.
- Your app updates its cached entitlements from the event and, if in doubt, fetches the current subscription from the billing API.
Treat webhooks carefully: verify every signature, process events idempotently because they can be delivered more than once, and don't assume they arrive in order. See webhook signature verification and payment webhooks best practices. A periodic reconciliation job that compares your cached plan with the billing system catches anything missed.
Handle the edge cases
Trials
Decide whether a trial gets the full feature set of the plan or a reduced one, and what happens on the day the trial ends without payment. See SaaS free trial strategy.
Downgrades
When a customer moves to a smaller plan, they may already be over a limit: 12 users on a plan that allows 5. Don't delete anything. Block adding more until they are within the limit, and tell them clearly what they need to change.
Failed payments
Don't remove features on the first failed payment. Give a grace period with a clear banner, then restrict the account to billing until it is paid, and restore everything immediately once it is. See suspending service for non-payment.
Usage limits
For limits counted per period, such as transactions per month, decide when the counter resets, whether you block or warn at the limit, and how customers can see their usage before they hit it.
Show entitlements in the interface
Gating is also a sales tool. Instead of hiding locked features entirely, show them with a short explanation and an upgrade link. Customers discover what the next plan offers, and support receives fewer "where is this feature?" questions.
Test it
Write automated tests for each plan's entitlements and for the edge cases above. A pricing change should be a data change plus a passing test run, not a hunt through the code base.
How CentraPoint helps
CentraPoint's customer subscriptions are the billing side of this pattern. You sell packages and plans, subscribe customers through the dashboard, the API or hosted checkout, and CentraPoint handles trials, renewals, dunning and cancellations. Signed webhooks such as subscription.created, subscription.plan_changed, subscription.past_due and subscription.cancelled tell your app when to update a customer's entitlements, and the Customer subscriptions API returns the current state whenever you need to check.
For grace periods and locks, CentraPoint's account standing tells your platform whether each customer is ok, in grace or locked to billing, and your app enforces it. CentraPoint uses the same model for its own plans: the Entitlements API returns an organisation's feature flags, limits and custom features, so integrations can check what is included instead of hard-coding plan names. See the entitlements documentation, the developers page and pricing.
Frequently asked questions
Should I check plan names or features in my code?
Features and limits. Plan names change for marketing reasons; entitlement keys should stay stable for the life of the product.
Where should entitlements be stored?
Keep the plan-to-entitlement mapping as data, cache each customer's effective entitlements in your app, and refresh them from billing events and a periodic check.
What happens to a customer's data when they downgrade?
Keep it. Block new usage above the new limit and ask the customer to reduce usage or upgrade, rather than deleting anything automatically.
- #saas
- #entitlements
- #subscriptions
- #webhooks
- #api