Entitlements (feature gating)
The machine-readable list of what a customer's plan actually unlocks, so your code checks capabilities instead of plan names.
See it
What it is
An entitlement is the machine-readable answer to 'is this customer allowed to do this right now'. It sits between billing and product as a small map of capabilities and limits: can_export_pdf true, seats 25, api_calls_included 10000. Billing writes to it when a subscription starts, upgrades, lapses, or ends; product only ever reads it.
The whole point is that your feature checks stop naming plans. if (plan === 'pro') scattered across 40 files means every new tier, every custom enterprise deal, and every grandfathered customer becomes a code change. if (entitlements.can_export_pdf) means it becomes a config change. Stripe ships this as a first-class Entitlements API, and vendors like Schematic and Flagsmith sell it as a service, but a features table joined to plans gets you most of the way.
Gotchas: enforce entitlements on the server, always, because a hidden button is decoration and not a paywall. Cache them (they are read on every request) but invalidate on subscription webhooks, or a downgraded customer keeps pro access for the length of your TTL. And decide explicitly what happens on payment failure versus cancellation: most products keep entitlements alive through a grace period, then downgrade to the free set rather than hard-locking the account and its data.
Ask AI for it
Add an entitlements layer between billing and the product. Define a features table of named capabilities (boolean switches like 'can_export_pdf' and numeric limits like 'seats' or 'projects'), map each plan to a set of feature values, and resolve a customer's effective entitlements from their active subscription plus any per-account overrides for custom deals. Expose a single server-side hasEntitlement / checkLimit helper and use it for every gate, never a plan-name comparison. Enforce it in the API handlers first and mirror it in the UI for affordances only. Cache resolved entitlements per customer and invalidate on subscription created, updated, deleted, and payment failed webhooks. On failed payment, keep current entitlements through a 7 day grace period, then fall back to the free tier set without deleting data.