#Subscriptions
#Plan vs subscription vs billing
| Term | Meaning | Lives in |
|---|---|---|
| Plan | What the customer can buy: tier, cycle, price, limits, features | Plan catalog Missing |
| Subscription | The account's/organization's active relationship with one plan: status, cycle, period, cancel flag | Subscription record |
| Billing | Money: wallet, payments, transactions, receipts, charges, tax | Billing tables + gateways. Specified by backend Phase 6, 2026-10-05 V8 requirement — see FE: Billing screens |
#Who owns the subscription
V7 background: one subscription per user in new_subscription_plans (user_id + the organization_id of the user's main organization); servers each have a new_subscriptions row pointing at that plan; permission checks use the organization owner's plan. V7 only
#Subscription flow
Plan selectionSubscription requestCheckout (if amount0)Payment (wallet or gateway)Backend verificationSubscription activeUpdated plan limitsUpdated dashboard
- The user selects a plan and cycle.
- BE quotes the amount (credit already paid, tax, promo).
- If the amount is 0 (a free plan — not a trial, V8 has none), it activates at once.
- Otherwise BE charges wallet credits. If credits are short, the user tops up through a gateway first (see Billing).
- BE confirms the payment (gateway verify / webhook), then activates or changes the subscription, writes a charge + audit entry, and updates the per-tier API rate limit (V7).
- FE reloads subscription, usage, permission map (features depend on the tier) and dashboard.
#States
V7 has no status column. State comes from expires_in_days, cycle and meta flags.
| V8 state | Meaning | V7 equivalent | UI |
|---|---|---|---|
trial | Not in V8 — Bhavik, 2026-10-09 Conflict. There is no trial, so no trial period and no days-left display | standard_trial_plan meta + trial days | Nothing to design. A new user goes to Choose a plan (/billing/plan) straight after sign-up instead |
trial_ended | Not in V8 — Bhavik, 2026-10-09 Conflict. Backend 7.6 still describes a trial-end gate; with no trial there is nothing to end | — (V7 had no such gate) | Replaced by the sign-up step. The blocking "pick a plan" moment moves from after a trial to immediately after sign-up, which is simpler: one required step, no timer. See FE: Plans & subscription |
free_forever | Removed for good — confirmed by Jayshree on 2026-10-08 V8 requirement, after half a day as a disagreement between the two docs. 7.21 no longer has a free-forever flag — it grants extra servers instead, which is not a subscription state at all. V7 free-forever users arrive with extra servers = 1 on an ordinary plan | — | No such state to design. Drop the badge and the no-renewal variant; a migrated V7 free-forever user looks like any other user on their plan |
locked | Day −15 after expiry; the owner's team members are locked too (7.12, 2026-10-05) V8 requirement | V7 locked account | Owner: locked screen with billing reachable. Member: the same screen naming the owner, with no billing tab and no pay button |
active | Paid and within period | expires_in_days ≥ 0 | Green badge, renewal date |
pending | Payment started, not verified yet | Transaction status = 2 (pending) | "Payment pending", no limits changed |
cancelled | Will not renew. Works until the period ends | subscription_plan_cancel = 1 | "Ends on |
expired | Period over. Backend status V8 requirement | expires_in_days < 0 (grace until −16) | Red banner + countdown. Every server action is blocked with "Plan has expired. Please renew it" (7.12), but the data stays readable and two things still work: delete a server and add credit / renew. So disable controls, don't grey out pages |
failed | Renewal or payment failed | Failed transaction / not enough credits | "Payment failed", Add credit / Retry |
renewal (event) | Period extended | renew-subscription | Toast + new date |
lifetime | Never expires, can't be cancelled | cycle = Lifetime | "Lifetime" badge |
#Expiry and renewal
- V7 ran a daily job counting the remaining days down. V8 keeps a real expiry date instead and checks it on every action (7.25) V8 requirement, so there is no counter to drift. Reminders still go out before the end, and the admin sets the timing: how many days before expiry they start (default 7), the warning day (default −7), the lock day (default −15) and which weekdays they are sent on (default Monday + Thursday) (7.10–7.12) V8 requirement. So no screen or translation string may contain those numbers — always the date from the API.
- Expired: every server action is refused with "Plan has expired. Please renew it" — but the user can still view their data, delete a server and add credit / renew (7.12) V8 requirement. This matches V7's
VerifyPermissionbehaviour and is now a written V8 rule. - Auto-renew keeps trying: if there wasn't enough credit on the expiry day, Central retries every day until the lock day (default −15) (7.10) V8 requirement. So adding credit during that window renews the plan by itself — the screens must not imply a Renew button has to be pressed afterwards.
- Renew within 15 days of expiry: the remaining (negative) days are kept. After that, a fresh period starts. V7 only
- Auto-renew: V7 renews by deducting wallet credits, with optional Stripe auto-recharge topping the wallet up. V8 keeps both: Phase 7 (7.10) renews from credit on the last day, and Phase 6 (6.5) keeps the Stripe saved card and auto-recharge that fills the wallet. V8 requirement D-4 answered.
- Price change (7.17) and feature / limit reduction (7.18): both can happen while someone is subscribed. The user is warned by email and the change applies at their next renewal, so the renewal amount and the coming limits must come from the API every time, never from the plan the user bought. V8 requirement
- What expiry does to servers (7.12, rewritten 2026-10-05): it depends on the type. Managed servers are powered off at the provider on the warning day and deleted at the provider on the lock day. Self-managed servers are only removed from Central and keep running at the provider. V8 requirement D-31 answered.
- Unlock (7.22): a locked account unlocks automatically once the user adds credit and pays the plan. Nothing removed at the lock day comes back by itself — a self-managed server has to be connected again, and a managed one no longer exists. V8 requirement
#Subscription screen (/subscription)
- Current subscription card: plan, cycle, state badge, period dates, price, payment source (wallet / card).
- Usage: servers, applications (with the cost caveat in Plans).
- Actions, each enabled only when the API allows it: Change plan, Change cycle, Cancel, Resume, Renew now.
- History: subscription events (from the audit log or charges).
#Required API (none exists)
| Capability | V7 reference | Status |
|---|---|---|
| Get current subscription + usage, with the expiry date and status (7.25) | GET /organizations/{org}/new-subscription-plan | rules V8 requirement, endpoint Missing |
| Create (first plan) | POST /create-subscription | Missing |
| Change plan / cycle | PATCH /change-subscription | Missing |
| Quote / remaining credit | GET /remaining-credit | Missing |
| Renew | PATCH /renew-subscription | Missing |
| Cancel / resume | PATCH /cancel-subscription, /resume-subscription | Missing |
| Promo codes | GET /available-promo-codes, GET /discount-percentage | Missing |
| Lifetime | POST /create-lifetime-subscription, PATCH /convert-to-lifetime | Missing Open question |