Churn Risk
Customer churn-risk and account-health scoring for SaaS retention & customer-success teams: score turns a bundle of usage/engagement/support/billing signals (login recency, usage trend, feature...
churn-risk
An intelligent microservice adapter pack that scores customer churn risk and account health for SaaS retention / customer-success teams. The weighted-signal scoring engine is deterministic and runs fully offline. Only the optional "save narrative" on score (with options.narrate) uses the shared LLM helper, and it silently falls back to a templated recommendation offline. Hybrid results are tagged { mode: 'heuristic' | 'llm' } — the score is always exact regardless of mode.
Tools
| Tool | What it does |
|---|---|
score | Turns a bundle of signals into a 0-100 risk score, a band (low/moderate/high/critical) and per-signal contributions. Optional LLM narrative. |
drivers | Ranks the top risk factors and the protective factors behind the score. |
segment | Buckets the account into a lifecycle segment (champion / healthy / passive / at-risk / dormant / likely-churn) with a recommended play. |
healthScore | Inverse 0-100 health index with an A–F grade and status. |
cohortRisk | Aggregates many accounts into a cohort distribution, at-risk MRR, expected revenue loss and the highest-risk accounts. |
renewalLikelihood | Estimates the probability the account renews and an expected renewal note. |
Signals
All optional — provide any subset; missing signals are dropped and the weights re-normalize:
daysSinceLogin, usageTrend (-1..1 or %), featureAdoption (0-1), seatUtilization (0-1),
nps (0-10), sentiment (-1..1), supportTickets, openBugs, paymentFailures,
daysToRenewal, monthsTenure, mrr
Usage
import pack from './index.js';
const signals = { daysSinceLogin: 21, usageTrend: -0.4, nps: 5, featureAdoption: 0.3, paymentFailures: 1, daysToRenewal: 25 };
await pack.adapters.score({ signals }); // { riskScore, band, contributions, ... }
pack.adapters.drivers({ signals }); // top risk + protective factors
pack.adapters.segment({ signals }); // lifecycle segment + play
pack.adapters.healthScore({ signals }); // health index + grade
pack.adapters.renewalLikelihood({ signals }); // renewal probability
pack.adapters.cohortRisk({ accounts: [ { id: 'A', mrr: 500, signals }, { id: 'B', mrr: 1200, signals: { nps: 9, usageTrend: 0.2 } } ] });
Custom weights (per-signal importance) can override the defaults for any tool.
DRY boundary notes
- Not generic stats:
numbers/statisticsprovide series primitives; this pack encodes the
retention scoring model, lifecycle segments and recommended plays on top of the domain signals.
- Not billing/finance: it consumes MRR/payment signals but does no invoicing or interest math
(invoice / finance own those).
- Self-contained: no cross-pack imports except
../_shared/llm.js.