Churn states
Six mutually exclusive states derived from a user's latest billing events — never stored, so they can't go stale.
| State | Meaning |
|---|---|
in_trial | Inside a free trial that hasn't resolved. |
converted | Paid — a trial that converted, or a direct purchase. |
cancelled | Auto-renew switched off; access continues until the period ends. |
expired | Access has actually ended. |
billing_issue | A payment failed and the card is being retried. |
none | No billing history at all. |
States are derived on read from the billing event stream — RevenueCat and Stripe webhooks — rather than written to a column, so a late-arriving event corrects history automatically. An UNCANCELLATION restores the state the user was in before they cancelled.
Cancelled ≠ expired
The distinction runs through the whole product (and the billing webhook): cancelled users still have access and are the win-back window; expired users don't. Treating the two as one state undercounts your recoverable revenue.
You'll meet the same states in the Trial outcomes card, on each row of the Users table, on the single-user page, and as the cohort axis in Cohort compare. Trial conversion rate is trial users who paid ÷ all trial users.