Plans and limits
The plan catalogue, what a null limit means, why usage is metered even when nothing is enforced, and the state of billing.
The catalogue
Plans are seeded from a catalogue at boot, so a fresh install has something to run on before anyone has configured anything. An operator can then adjust a customer's ceiling without a redeploy.
| Plan | Price | Servers | Applications | Build minutes | Listed |
|---|---|---|---|---|---|
self-hosted | Free | Unlimited | Unlimited | Unlimited | No |
starter | $9/mo | 1 | 5 | 300 | Yes |
team | $29/mo | 5 | 30 | 1,500 | Yes |
scale | $99/mo | Unlimited | Unlimited | 10,000 | Yes |
self-hosted is not listed because it is what you get by installing, not
something to choose in a hosted portal. The paid tiers' prices are this
repository's opinion, not a commercial decision anyone has signed off.
Money is stored in integer minor units. Never floats.
A null limit is unlimited, never zero
Every one of self-hosted's limits is null. That is what makes the enforcement code inert
on a self-hosted box rather than absent from it — one path through the product, exercised by
everyone.
Enforcement
BILLING_ENFORCE_LIMITS=false # the default
BILLING_DEFAULT_PLAN=self-hostedOff is the self-hosted case: the machine belongs to the person running it, and a ceiling on their own hardware would be an insult rather than a product.
Usage is metered either way
The flag decides whether a limit refuses something, not whether it is measured. Turning it on does not begin from a blank meter.
An organization with no subscription is treated as being on BILLING_DEFAULT_PLAN, which must
match a slug in the seeded catalogue.
Changing a plan
PUT /subscription is operator-gated by decorator. With the manual provider a plan change is
a grant — and a member who could grant themselves the largest plan would make every limit
decorative.
GET /plans lists the public catalogue. The marketing site's pricing page reads it live, so
prices are never a second copy that drifts.
Billing
No payment processor is integrated
Deliberately. The choice between Stripe, Razorpay, and Paddle is a commercial one that is still open, and webhook handling plus a customer mapping written against a guess would be thrown away.
There is a BillingProvider seam with ManualBillingProvider bound to it. The manual
provider is a real implementation, not a stub: it is the correct one for a self-hosted
install, which has no processor and never will.
Subscription status
A subscription carries one of TRIALING, ACTIVE, PAST_DUE, or CANCELED, so a hosted
deployment can express the states a processor would drive. With the manual provider, a
subscription is whatever an operator granted.