You have a list of Stripe subscribers and a cancel status for each. How long do plans stay active, and which columns go with cancelling? This analysis estimates how long subscriptions stay active, by group, and looks for drivers of cancellation. Export your Stripe subscriptions and upload the CSV.
Worked Example (Simulated)
Question: In this made-up group, what share may still be active after six months?
Inputs: Made-up data, not Stripe records. The script needs numpy. It makes 120 subscriptions, 60 Basic and 60 Pro, with seed 23. The script sets cancel rates of 10% a month for Basic and 5% a month for Pro, so the true shares still active at six months are 54.9% and 74.1%. For each subscription it picks a time to cancel and a time when follow-up ends. If follow-up ends first, we do not know if or when that person would cancel. This is called censoring. The time unit (months) is an assumption of this example; the script has no unit.
Method: The Kaplan-Meier estimate tracks how many stay active over time. At each known cancel time it updates the share still active among those still in the study. A censored row counts up to its last follow-up time.
import numpy as np
SEED = 23
N_PER_PLAN = 60
rng = np.random.default_rng(SEED)
rows = []
for plan, hazard in (("Basic", 0.10), ("Pro", 0.05)):
event_time = rng.exponential(scale=1 / hazard, size=N_PER_PLAN)
censor_time = rng.uniform(4, 12, size=N_PER_PLAN)
duration = np.minimum(event_time, censor_time)
event = event_time <= censor_time
rows.extend((plan, float(t), bool(e)) for t, e in zip(duration, event))
def km_survival(rows, horizon):
survival = 1.0
times = sorted({t for _, t, event in rows if event and t <= horizon})
for t in times:
deaths = sum(1 for _, time, event in rows if event and time == t)
at_risk = sum(1 for _, time, _ in rows if time >= t)
survival *= 1 - deaths / at_risk
return survival
print(f"Simulated data, seed {SEED}")
print(f"Input: {len(rows)} subscriptions; 60 Basic and 60 Pro; "
"follow-up capped at 12 months")
for plan in ("Basic", "Pro"):
subset = [row for row in rows if row[0] == plan]
events = sum(row[2] for row in subset)
survival = km_survival(subset, 6)
print(f"{plan}: {events} cancellations observed; Kaplan-Meier estimate "
f"still active at 6 months = {survival:.3f} ({survival:.1%})")
Printed output:
Simulated data, seed 23
Input: 120 subscriptions; 60 Basic and 60 Pro; follow-up capped at 12 months
Basic: 29 cancellations observed; Kaplan-Meier estimate still active at 6 months = 0.525 (52.5%)
Pro: 21 cancellations observed; Kaplan-Meier estimate still active at 6 months = 0.676 (67.6%)
Result: At six months, the estimate is 52.5% for Basic and 67.6% for Pro. Pro's estimate lands below its set value of 74.1% by chance with 60 subscriptions. The 29 Basic and 21 Pro cancellations are counted over the whole follow-up, up to 12 months, not only through month six.
Limit: These are made-up data, not Stripe records. They cannot show why people cancel or what will happen at another firm. In the script, cancelling and the end of follow-up are independent by construction.
Sources
- Kaplan, E. L., and Meier, P. (1958). Nonparametric Estimation from Incomplete Observations. Journal of the American Statistical Association. doi:10.1080/01621459.1958.10501452. Cited for the Kaplan-Meier method (who and when).
What Does Churn Prediction Show?
A Kaplan-Meier curve estimates how long subscriptions stay active. It does not predict whether one particular customer will cancel. The analysis takes the start date and churn status of each subscription and estimates the share still active at each point in time. Subscriptions that are still active are treated as "censored" observations: we know they have lasted at least this long, but we do not yet know when (or if) they will cancel.
The report also looks for drivers of churn with a logistic regression. A driver is a column that goes with cancelling in your data. That is an association, not proof of cause.
When to Use It
Use this analysis if you bill customers on a recurring basis through Stripe and want to know how long they stay. Useful questions include: which plan tier keeps subscribers longest, whether monthly billing goes with more cancelling than annual billing, and whether customers who start with a free period stay for a different length of time than customers who paid from day one.
You can run it again after a pricing change or before budgeting season to compare how long plans stay active. Aggregate churn rates can hide segments that lose subscribers faster than others, so compare groups as well as the total.
What Data Do You Need?
You need a CSV export of your Stripe subscriptions. The free tool needs a start date and a churn column. The churn column can be a cancel date (blank means still active), a 0/1 flag, or yes/no text. Other columns, such as plan name or billing interval, can be used as possible drivers.
The tool needs at least 30 customers and at least 5 cancellations to run. With few cancellations the intervals are wide.
How to Read the Report
The survival curve shows the estimated share of subscriptions still active at each time since the start date. The curve steps down at each known cancel time. A steep early drop means many subscriptions end soon after they start. A flat stretch means few cancellations in that period. Where the curve is based on few subscriptions, treat it with care.
The drivers come from a logistic regression of churn status on the other columns. A column that goes with cancelling is a lead to investigate, not proof that it causes cancelling. Compare churn by plan: a gap is a summary of the data, and by itself it does not show a real effect.
What to Do With the Results
- Look at the shape of the curve: if cancellations cluster early, check the first weeks of onboarding.
- Compare plans: if one plan drops faster than another, ask what differs in who buys it and how it is billed.
- Test a change before you scale it: a driver found in past data is a question for a controlled test.
When to Use Something Else
If you want to understand customer behavior patterns rather than cancellation, consider RFM segmentation. RFM groups customers by Recency, Frequency, and Monetary value.
If you are looking at retention from a cohort perspective (what percentage of customers who signed up in January are still active in March) use cohort retention analysis. Cohort analysis shows retention curves for groups defined by signup date, a different lens than the plan-based comparison here.
The R Code Behind the Analysis
Every report names its method and includes the R code that produced it, so you can reproduce, audit and cite it. The method code is fixed, not rewritten for each run, so the same data gives the same analysis every time.
The analysis uses the survival package for survival curve estimation via survfit(), which gives the Kaplan-Meier curves. Drivers are found with a logistic regression. Every step is visible in the code tab of your report.
Your turn
Bring your own data and the question you actually need answered.
MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai