Churn modeling · Decision policy · Model serving

RetentionLab

End-to-End Customer Retention Analytics Platform

From churn prediction to retention decisions — a leakage-safe machine learning system combining calibrated risk modeling, constrained targeting, experiment design, model serving, and drift monitoring.

7,043
Customer Records
IBM fictional Telco sample
0.855
ROC-AUC
Held-out test split, scored once
0.670
PR-AUC
Against 26.5% prevalence
51.1%
Churners Captured
within the highest-risk 20%
2.55x
Lift vs Random Targeting
Retrospective ranking, not a causal effect

The decision problem

Not "predict churn" — decide who to contact

A retention team has limited outreach capacity, so the model must produce useful probabilities, prioritize customers under a budget, and support an experiment capable of measuring whether an intervention actually reduces churn. Classification accuracy alone answers none of those questions.

1

7,043 customers

Observational records, no treatment assignment

2

Predict churn probability

Gradient boosting over 19 validated features

3

Calibrate risk

Probabilities usable as numbers, not just ranks

4

Apply outreach capacity

The retention team cannot contact everyone

5

Rank customers

Highest predicted risk first

6

Target the top cohort

51.1% of churners inside the top 20%

7

Test with an RCT

The only way to measure a causal effect

4,929 / 1,057 / 1,057
Train / validation / test split
Stratified, seed 42; the test split is scored exactly once, after every modeling choice is final.
26.5%
Churn prevalence
The positive class is a minority, which is why ranking quality matters more than raw accuracy.
19
Validated model features
The customer identifier and the target are excluded from the feature frame and asserted absent by tests.

Model performance

Measured once on a held-out split

PR-AUC was the primary selection criterion because the positive churn class is substantially smaller than the retained class. Accuracy is reported but was deliberately not used to choose the model — the two metrics disagree here.

0.855
ROC-AUC
Ranking quality across all thresholds.
0.670
PR-AUC
Against a 26.5% prevalence baseline.
0.1324
Brier score
Probability quality, not just ordering.

Model selection (validation split)

Chosen on PR-AUC, then Brier score.

ModelPR-AUCROC-AUCBrier
Logistic Regression 0.6280.8300.1408
Hist Gradient Boosting selected0.6430.8330.1392

Calibration (validation split)

Cross-validated on training data, compared on validation. The gain is real but small, and slightly reduces PR-AUC — reported as measured.

VariantBrierPR-AUC
uncalibrated0.139190.643
sigmoid0.138090.639
isotonic0.138190.641

Generated diagnostics

These are the figures written by the analytical pipeline, served directly from reports/figures/. Nothing is redrawn.

ROC curve
ROC curveHeld-out test split with the random-classifier diagonal.
Precision-recall curve
Precision-recall curvePrevalence baseline shown for reference.
Calibration curve
Calibration curveCalibrated against uncalibrated probabilities.
Confusion matrix
Confusion matrixAt the 0.5 decision threshold.

Retention policy

Outreach capacity versus churner capture

Customers are ranked by calibrated risk and the top slice is contacted. The marker on each bar shows what random targeting of the same size would be expected to reach.

Top 10% · 106 customers28.6% of churners · 2.85x lift
Top 20% · 212 customers51.1% of churners · 2.55x lift
Top 30% · 318 customers66.1% of churners · 2.20x lift
20% outreach capacity
→
51.1%churner capture
→
2.55x lift over random targeting
→
67.5% of contacted did churn
CapacityContactedChurners caught CapturePrecisionLift
Top 10%10680 / 28028.6%75.5%2.85x
Top 20%212143 / 28051.1%67.5%2.55x
Top 30%318185 / 28066.1%58.2%2.20x
Cumulative gains curve
Cumulative gainsGenerated by the pipeline: churner capture across every capacity, with the random-targeting diagonal.
This measures predictive prioritization only. It shows the model ranks customers who did churn near the top of a held-out split. It does not show that contacting them prevents churn — a perfectly targeted campaign with a useless offer would produce this same table and retain nobody.

Interactive demo

Score a customer against the deployed model

This form posts to the live POST /predict endpoint and renders the response. Nothing is simulated in the browser. Inputs are generated from the service's own Pydantic schema, so they match the 19-feature contract exactly.

Customer

Services

Account

Derived

—

Computed as tenure × monthly charges so the submitted record stays internally consistent, then validated by the API.

Example customers are illustrative fictional records authored for this page, not rows from the IBM dataset, and carry no churn labels. Display bands: Lower: 0.00–0.30 Elevated: 0.30–0.60 High: 0.60–1.00 — presentation categories only, not a business decision threshold.

Capacity-constrained ranking

Rank a cohort under a fixed outreach budget

12 illustrative customers are scored and ordered by the live POST /rank endpoint. Change the capacity to see which customers a retention team would actually contact.

Outreach capacity

Fictional records with no churn labels: this demonstrates the ranking mechanism, not measured outcomes.

Experiment design

Prediction is not causation

The model decides whom to prioritize. A randomized experiment is still required to determine whether a retention intervention actually works. This dataset contains no treatment assignment, so the project ships a power analysis instead of an effect estimate.

67.5%
Observed churn, top-20% cohort
Measured, not assumed: the churn rate among customers a top-20% policy would contact.
3 pp
Target detectable reduction
An assumption for sizing, not an observed effect.
80%
Statistical power
Two-sided two-proportion test at α = 0.05.
Control
3,915
customers, no offer
versus
Intervention
3,915
customers, retention offer
Prospective design and power analysis only. No experiment has been conducted, and 7,830 customers would be required in total to detect the assumed effect. The effect size is an input to the calculation, never a result of it.

System architecture

From raw records to a verified public endpoint

Two halves, one artifact: the analytical pipeline produces a frozen model, and the serving layer verifies that exact artifact before it answers a request.

Data science

IBM Telco Sample7,043 labelled customer records
Schema ValidationColumns, duplicates, target values, numeric parsing
Leakage-Safe PreprocessingTransformers fitted on the training split only
Model ComparisonInterpretable baseline vs nonlinear challenger
HistGradientBoostingSelected on validation PR-AUC
Probability CalibrationCross-validated, chosen on validation Brier
Untouched Test EvaluationHeld-out split scored exactly once
Retention RankingCapacity-constrained prioritization
Experiment DesignProspective power analysis

ML engineering

final_model.joblibFrozen serialized pipeline
SHA-256 VerificationChecked before the model is served
FastAPI ServiceTyped request contract, safe error surfaces
Prometheus MetricsSix instrumented metric families
Vercel DeploymentStateless Python serverless function
/predict/batch-predict/rank/monitor/drift

Production engineering

What makes it a service rather than a notebook

19
Model contract
validated model features
SHA-256
Artifact integrity
verified before inference
1,000
Batch inference
customer maximum per request
87
Testing
automated tests, zero skipped
184/184
Documentation integrity
numeric claims verified against artifacts
6
Observability
Prometheus metric families

Technology

PythonLanguage
scikit-learnModeling & calibration
pandasData handling
NumPyVectorized inference
statsmodelsPower analysis
FastAPIInference service
PydanticSchema validation
pytestAutomated tests
RuffStatic analysis
PrometheusInstrumentation
DockerContainer definition
GitHub ActionsCI
VercelPublic deployment

Python 3.10.20 · scikit-learn 1.6.1 — the deployed runtime installs the same version that produced the serialized artifact. The Dockerfile is included in the repository; container execution was not verified locally.

Drift monitoring

Watching the inputs, not just the outputs

Numeric drift — Population Stability Index

Monitored: tenure MonthlyCharges TotalCharges

Incoming batches are compared against a reference profile built from the 4,929 training rows only, using fixed bins so scores stay comparable.

< 0.10Little apparent shift
0.10 – 0.25Investigate
≥ 0.25Substantial apparent shift

These are operational rules of thumb for triage, not formal statistical significance thresholds.

Categorical drift — total variation

Monitored: Contract InternetService PaymentMethod

Category distributions and missingness rates are compared against the same training-only reference. POST /monitor/drift returns per-feature scores, an overall status, and any warnings.

No production drift has been observed or is claimed. The endpoint scores whatever batch you send it; this project has no production traffic history.

Serving benchmark

Batch size versus p95 latency

Vectorized inference: a 500-customer batch costs roughly twice a single-customer request, not 500 times.

batch 116.32 ms
batch 1016.68 ms
batch 10020.89 ms
batch 50036.15 ms
BatchDirect p50Direct p95 HTTP p50HTTP p95
114.0614.3915.6616.32
1014.4416.1916.1116.68
10016.5817.1719.5520.89
50027.2729.9134.6036.15
Local FastAPI TestClient benchmark — not production network latency. Measured in-process on Darwin 25.5.0 arm64 over 50 iterations. These are not Vercel response times and say nothing about internet-facing performance.

Inspect the system

Every claim on this page is checkable

The interactive documentation is the full request contract. The project summary endpoint returns the exact artifact-derived payload this page renders.

Engineering notes

Limitations

Stated plainly, because knowing what a result does not support is part of the result.

IBM's fictional Telco sample dataset, not real customer records.
Observational data with no treatment assignment of any kind.
Predictive ranking does not establish a causal retention effect.
The randomized experiment is designed and sized, not conducted.
Latency figures come from a local benchmark, not production network traffic.
This is a portfolio deployment: no real traffic, no availability guarantee.
Prometheus counters are per-instance on serverless and are not globally durable.