Lester Leong
Churn Prediction Models: When They Are Worth It (And When a Metric Is Enough)
A Churn Model Is Usually Theater
The request arrives in almost the same words every time. "We have a churn problem. Can we build a model to predict it?" The instinct is reasonable. Churn is expensive, machine learning is supposed to be good at prediction, and a model feels like the serious, modern response. In most cases it is the wrong response. The team spends six weeks engineering features and tuning a gradient boosting classifier, ships a dashboard that ranks accounts by churn probability, and then discovers the hard part was never the prediction. It was having something to do with it.
I have watched this play out in three different environments. On the consulting side, across 20+ SMBs and startups at Gradient Growth, teams routinely ask me for a model before they have a single working retention play. At a financial social media startup before its acquisition, we had the data to build one and learned that a metric plus two rules captured most of the value. And now on a GenAI squad at a major finance technology company, where the bar for shipping a model into a production loop is high precisely because we have seen how often the model is the easy 20% and the operational wiring is the brutal 80%. The pattern holds across all three: the modeling is rarely the constraint.
This is not an anti-ML argument. A churn prediction model can be genuinely valuable. But it is valuable under specific, checkable conditions, and the failure mode is not a bad model. The failure mode is a good model that predicts churn nobody can prevent. A high AUC in a notebook is not an outcome. Retained revenue is an outcome, and the distance between those two things is where most churn projects quietly die.
The Three Conditions
Before you write a line of modeling code, three conditions all have to hold. If any one fails, a [churn metric](/insights/how-to-calculate-churn-rate) plus simple rules will beat the model, and it will beat it for less money and less maintenance.
Condition 1: You Can Identify At-Risk Users Early Enough to Act
A churn prediction has to arrive while you can still do something about it. This sounds obvious and is constantly violated. If your model flags an account as high risk three days before the renewal date, and your save play needs two weeks to run (executive outreach, a custom plan, a renegotiated contract), the prediction is correct and useless.
The relevant question is lead time, not accuracy. You need the signal to fire far enough ahead of the churn event that your intervention has time to work. For a monthly self-serve SaaS product where users lapse silently, that might mean flagging declining engagement 21 days before the typical churn point. For annual B2B contracts, it might mean 60 to 90 days before renewal. If your data does not contain a leading signal at that horizon, no model can manufacture one. Boosting will happily fit the trailing signals (the user already stopped logging in) and report a beautiful in-sample number that, operationally, is a death certificate rather than a diagnosis.
Condition 2: You Have an Intervention That Actually Changes the Outcome
This is the condition teams skip, and it is the one that matters most. A churn model is only worth its cost if you have a save play with demonstrated lift. Not a save play you hope works. One you have tested.
The clean way to know is a holdout. Take a sample of at-risk accounts, intervene on a random half, leave the other half alone, and measure the difference in retention. If the treated group retains meaningfully better than the control, you have a real intervention and the prediction has somewhere to go. If there is no measurable difference, then ranking accounts by churn risk is an elaborate way to generate a list nobody can act on. I have seen teams skip this test, ship the model, and run save plays for a year without ever knowing whether the plays did anything. That is not a measurement problem. It is a strategy that never had a feedback loop.
Condition 3: The Base Rate and Volume Make the Effort Worthwhile
Churn is usually an imbalanced problem, which is both why a model can help and why it can be a waste. If you churn 2% of accounts a month and you have 400 accounts, you are losing roughly 8 accounts a month. A model that perfectly ranked them would still be operating on tiny numbers, and a human reviewing a weekly list of declining accounts would capture most of the value with none of the infrastructure. The math only favors a model when volume is high enough that manual review does not scale and the dollar value of the saved accounts clears the cost of building and maintaining the system.
A useful framing: the model is worth building when the expected retained revenue from acting on its predictions exceeds the fully loaded cost of building it, running it, and operating the intervention. We will put real numbers on that below. Until you have run that calculation, "build a churn model" is a vibe, not a decision.
The Features Are a Health Score You Already Have
Here is the part teams overcomplicate. The features that predict churn are the same signals that belong in a [B2B customer health score](/insights/customer-health-score-b2b). You are not inventing a new feature set. You are reusing one.
The durable predictors, in rough order of usefulness:
1. Usage recency. Days since last meaningful action. The single strongest churn signal in almost every product I have worked on. An RFM-style recency feature alone often gets you most of the way. 2. Usage frequency and its trend. Not just how often, but whether frequency is rising or falling. A user at 10 sessions a week trending to 4 is a louder signal than a user steady at 5. 3. Tenure. Churn hazard is rarely flat over the account lifecycle. New accounts churn for onboarding reasons, mature accounts churn for value reasons, and a tenure feature lets the model separate them. 4. Breadth of adoption. Number of distinct core features used. Single-feature users churn at multiples of the rate of users integrated across the product. 5. Support and friction signals. Ticket volume, severity, unresolved issues, failed payments. These are sparse but high-signal when present.
Two engineering notes that save you from yourself. First, compute every feature as of a point in time strictly before the churn label window, or you will leak the future into your features and ship a model that looks brilliant in the notebook and falls apart in production. Leakage is the most common and most embarrassing failure in churn modeling. Second, trend features (the slope of usage over the trailing weeks) usually carry more signal than levels, because a healthy-looking absolute number that is collapsing is exactly the account you want to catch.
The Model: Start Honest, Earn the Complexity
Logistic regression is the honest baseline. It is fast, it is interpretable, the coefficients tell you which signals drive risk, and it is a genuinely hard baseline to beat on tabular churn data with a sensible feature set. Start here. If logistic regression on good features does not produce a usefully ranked list, a fancier model rarely rescues the project. The problem is the features or the framing, not the algorithm.
Gradient boosting earns its place when there are real interactions and nonlinearities the linear model cannot capture (recency matters differently for new versus mature accounts, support tickets matter only above a frequency threshold) and when you have enough churn events to fit a more flexible model without overfitting. The gain over a clean logistic baseline is usually modest, frequently a few points of lift, and you should measure that gain explicitly rather than assume it.
The sketch below fits a model and, critically, evaluates it the way that matters. Note what it does not report.
```python import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.ensemble import GradientBoostingClassifier from sklearn.model_selection import train_test_split
def precision_at_k(y_true, y_score, k_frac=0.05): """Precision among the top k fraction of accounts by predicted risk.""" n = len(y_true) k = max(1, int(np.floor(k_frac * n))) top_idx = np.argsort(y_score)[::-1][:k] return float(np.mean(np.asarray(y_true)[top_idx]))
def lift_at_k(y_true, y_score, k_frac=0.05): """How many times better than the base rate the top k accounts are.""" base_rate = float(np.mean(y_true)) return precision_at_k(y_true, y_score, k_frac) / base_rate
# X: engineered features (recency, freq_trend, tenure, breadth, tickets) # y: 1 if the account churned in the label window, else 0 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.25, stratify=y, random_state=7 )
# honest baseline logit = LogisticRegression(max_iter=1000, class_weight="balanced") logit.fit(X_train, y_train) p_logit = logit.predict_proba(X_test)[:, 1]
# the more flexible model, only kept if it earns its complexity gbm = GradientBoostingClassifier(random_state=7) gbm.fit(X_train, y_train) p_gbm = gbm.predict_proba(X_test)[:, 1]
for name, p in [("logit", p_logit), ("gbm", p_gbm)]: print( name, "precision@5%:", round(precision_at_k(y_test, p, 0.05), 3), "lift@5%:", round(lift_at_k(y_test, p, 0.05), 2), ) ```
There is no `accuracy_score` call in that sketch, and its absence is the entire point.
Why Accuracy Is the Wrong Target
On a churn problem with a 4% monthly base rate, a model that predicts "nobody churns" is 96% accurate. It is also worthless. Accuracy on an imbalanced problem rewards you for ignoring the minority class, which is the only class you care about. Teams that optimize accuracy talk themselves into shipping models that have learned to say no.
AUC is better but still misleading for this use case. AUC measures ranking quality across the entire probability range, but you are never going to act on the entire range. You are going to act on the top slice (the riskiest 3%, 5%, maybe 10% of accounts) because that is all your save team has the capacity to touch. A model can have a respectable AUC and still be mediocre exactly where you operate. What you want to know is: among the accounts I will actually contact, how many were going to churn?
That is precision@k. It answers the operational question directly. Pair it with lift@k (precision@k divided by the base rate) to express the gain over doing nothing, and you have an evaluation that maps to dollars instead of to a leaderboard. The deeper version of this argument, that teams routinely [optimize the wrong metric](/insights/ab-testing-wrong-metric) and then act surprised when nothing improves, applies to churn modeling as squarely as it applies to experiment design.
A Worked Example: Does the Model Pay?
Numbers make this concrete. These are illustrative, but the structure is exactly what I run in an engagement.
Say you have 10,000 active accounts. Monthly churn base rate is 4%, so 400 accounts churn per month. Average account value is 2,000 dollars in annual recurring revenue. Your save team has the capacity to work the top 5% of accounts by risk each month, which is 500 accounts.
Step 1: Find the true positives in the contacted set. Suppose precision@5% is 40%. Of the 500 contacted accounts, 0.40 times 500 equals 200 are genuine churners. (For context, the base rate is 4%, so the model is concentrating churners at 10x the base rate in the top slice. That is a strong but realistic lift@k of 10.)
Step 2: Apply the save play's real effectiveness. Assume your holdout test showed the intervention works on one third of true positives. Then 200 times 0.33 equals roughly 66 accounts retained that would otherwise have churned.
Step 3: Convert to revenue. 66 accounts times 2,000 dollars equals 132,000 dollars in annual recurring revenue retained per monthly cycle of the program. Even if you only credit a single annual cohort and apply a conservative haircut for accounts that would have been saved anyway, this is a large number.
Step 4: Compare to cost. A churn model is not free. Budget the build (a few weeks of a data scientist), ongoing maintenance and monitoring, and the operational cost of the save team contacting 500 accounts a month. If that fully loaded cost is, say, 40,000 to 60,000 dollars a year, the program clears its cost comfortably and the model is worth building.
Now change one input. Suppose the save play only works on 5% of true positives instead of 33%, because nobody ever tested it and it turns out a discount email does not save accounts that left for product reasons. Then you retain 200 times 0.05 equals 10 accounts, or 20,000 dollars, and the program may not clear its cost at all. The model did not get worse. The intervention was always weak; the model just made the weakness expensive to discover. This is condition two doing its job in the arithmetic. The effectiveness of the save play, not the quality of the model, is the swing variable.
One more swing variable worth stress-testing: precision@k itself. If precision@5% is 20% instead of 40%, you halve the true positives and halve the retained revenue. This is why you evaluate at k, the place you operate, rather than reporting a single global metric and hoping.
The Model Is the Easy Part
The honest summary is the same one I give about whether [AI will replace analysts](/insights/will-ai-replace-data-analysts): the modeling is the commoditized, learnable, increasingly automated part. The hard part is the operational loop around it, and that part is mostly judgment and organizational follow-through, not algorithms.
A churn model that pays off requires a chain where every link holds. You need a leading signal with enough lead time. You need that signal scored and delivered to a team on a cadence they can act on. You need a save play that has been tested against a holdout and shown to move retention. You need the capacity to work the list. And you need someone monitoring whether the whole loop is actually retaining revenue, because models drift, save plays decay, and a churn system that is not measured against retained dollars degrades into theater within a couple of quarters. Break any link and the AUC on the slide deck means nothing.
So the practical sequence is the reverse of what most teams do. Do not start by building the model. Start by establishing whether you have an intervention that works, whether you can act early enough, and whether the volume justifies the effort. If all three hold, build the simplest model that produces a usefully ranked list, evaluate it on precision@k and expected retained revenue, and wire it into a loop you will actually run. If any of the three fail, skip the model. A churn metric, a weekly review of the steepest engagement declines, and one tested save play will outperform a sophisticated classifier that predicts churn you were never going to prevent.
The most expensive churn model is the one that works perfectly and changes nothing.
---
I help teams decide when a churn model is worth building and wire the ones that are into an intervention loop that actually retains revenue. [lester@gradientgrowth.com](mailto:lester@gradientgrowth.com)