Two separate decisions
What goes in each tier? This is what makes “Free” different from “Pro”, and it’s decided once per tier. What happens when someone wants more than their tier includes? Do they hit a wall and have to upgrade, or do they keep going and pay for the excess? The second one is decided per thing you’re limiting, not per tier — and the answer can be different for every one of them. A single tier can hold something that hard-stops at five, something that keeps serving and charges for the excess, and something that’s simply free forever.The vocabulary, once: a feature is one thing you might limit or grant. What a tier gives someone
for that feature is an entitlement. A plan is the tier itself, and a price is what it
costs. Your code checks the entitlement, never the plan name:
Decision 1: What goes in each tier
The standard “Good-Better-Best” shape: each tier gives more than the one below it, and most of what separates them is either on/off or a number.- Create features:
can_access_dashboard,can_invite_members. - Create plans:
- Free Plan: Includes
can_access_dashboard. - Pro Plan: Includes
can_access_dashboard+can_invite_members.
- Free Plan: Includes
Decision 2: What happens when someone wants more
For anything you limit by a number, pick what happens once it runs out. Nothing here is “more advanced” than the others — they’re three different answers to the same question, and which one fits depends on what you’re selling, not on how sophisticated your pricing looks.Option A: Stop there — a hard limit, never billed
Nobody pays their way past this. The plan simply refuses once the allowance is gone. This is not usage-based pricing — nothing is ever charged for going over, because going over isn’t allowed. Right for things a customer should decide to buy more of by upgrading, not discover as a surprise line on an invoice: seats, projects, connected devices.- Create a feature
team_seatswith type Quota. A seat is a standing count rather than a monthly consumption, so set it to never renew instead of resetting each period. - On the plan, set the allowance to
5and choose to stop access past it. - Gate the action with
consume(), which checks and increments atomically:
kerne.admin.adjustUsage('team_seats', { customer: orgId, delta: -1 }). A counter that never renews is the one place that matters — a per-period quota would have cleared itself anyway.
Option B: Keep going and charge for it — pay-as-you-go past the included amount
The same feature, the opposite choice: past the included amount the customer keeps going and you bill the excess. This is “0.01 per email past 10,000” — genuinely usage-based, unlike Option A.- Open that feature’s cell on the plan and choose to keep serving past the allowance and charge for it.
- Write the rate the way you sell it —
0.01 EUR per message, or5.00 EUR per 1,000if that’s the quantity you price by. Kerne creates the meter and its price at Stripe; you never leave for the Stripe dashboard and never copy an id back. - Optionally add a spending cap — a ceiling in money. Past it usage still counts and still works, it just stops being billed. Leave it empty for an add-on meant to scale freely.
useUsage.
Rates aren’t limited to one number. The quantity you sell by, a schedule of tiers, and whether a tier reprices everything or only its own slice are all part of the same rate — see Usage billing.
Option C: The limit isn’t one pool
Orthogonal to A and B, not a third alternative to them: the customer is one payer, but the thing you meter isn’t one pool — per machine, per project, per seat, per one of their clients. Declare what the feature is counted by, then apply Option A or B on top, and choose whether the allowance and the ceiling are shared across the account or per slice.Add-ons
A customer holds one live subscription at a time — one payer, one plan. That is enforced in the database, and it is the first thing to know before designing an add-on, because it rules out the shape most people reach for: an add-on is never a second subscription sitting next to the first. It is one of these instead:A metered feature
Nothing included, a rate, no cap. The customer pays for exactly what they turn on, and it reaches the same invoice. This is the usual answer.
A plan variant
Two plans that differ by one entitlement. Right when the add-on is a lasting choice rather than something toggled.
An override
A negotiated extra on one account, outside the catalog. For deals, not for a product line.
0 and the ceiling left empty. Combine it with Option C when the add-on is bought per project or per seat rather than once per account.
Because add-ons ride the subscription rather than sitting beside it, a plan change carries them along: switching plans re-pins entitlements to the new plan, so an add-on that exists on one plan and not the other stops with the switch. Model an add-on you intend to survive a plan change as a feature present on every plan, with a different allowance.
Which shape fits
A quota that gets billed has to restart at zero each period. “Unused allowance carries over” and “bill the excess” together would charge last period’s units again, so the two can’t be combined.

