SaaS9 min

Churn analytics: detecting, preventing, and recovering from SaaS churn

How to spot churn before it happens — leading indicators, cohort retention, dunning tuning, winback campaigns, and the analytical traps that make most churn reports worse than useless.

Most SaaS churn reporting is a postmortem. A customer cancels, the dashboard blinks, the number ticks up, and the team tries to reconstruct what happened from whatever data it kept. That workflow produces feelings, not interventions. A churn analytics program worth the engineering investment does three things instead: it detects risk with enough lead time to act, it separates the churn the product can fix from the churn it can't, and it recovers the revenue that's already walking out the door. This post covers the shape of that program — leading indicators, cohort retention, dunning tuning, winback campaigns, and the analytical traps that make most churn reports worse than useless.

Voluntary vs involuntary: two different problems

Lumping all cancellations together is the first mistake. The two kinds have different causes, different fixes, and different ownership inside the company. Voluntary churn — the user clicks 'cancel' — is a product and customer-success problem. Involuntary churn — a card expires, a bank declines a charge, a 3DS flow times out — is a billing and payment-infrastructure problem. They look the same in a revenue chart and almost nothing in the same report points at the same fix.

Benchmarks that keep showing up across client data: B2B SaaS monthly churn averages around 3.5%, split roughly 2.6% voluntary and 0.8% involuntary. The involuntary slice feels smaller — it isn't. Involuntary churn makes up 20–40% of total churn for most SaaS companies because failed payment recovery compounds over a customer's lifetime. Fixing it is one of the highest-ROI retention investments a team can make, largely because the customer already wants to be paying.

Leading indicators — the signals that give lead time

A churn signal only matters if it fires before the user has decided to leave. By the time support tickets are going ignored and the last-login date is three weeks old, the conversation has already happened inside the customer's team. The signals worth tracking fire weeks earlier than that — when the behavior starts changing but the contract is still active.

SignalTypical lead timePlaybook
Login frequency drop (50%+ vs trailing 30d)45–60 daysCSM check-in, re-onboarding email on top features
Active seat count drop30–45 daysSurface usage report to admin, offer seat consolidation
Feature breadth narrowing (1–2 features only)30–60 daysTargeted education on adjacent features that lift retention
Support ticket spike + negative sentiment15–30 daysEscalate to named owner, weekly call until resolved
Failed renewal quote / admin asked for cancellation URL7–14 daysExecutive outreach, retention offer, honest win/lose call
Card about to expire (next 30 days)MechanicalPre-emptive card update email, in-app prompt on next login
Payment failure0–7 daysDunning sequence, in-app banner, account-manager ping for enterprise

A churn risk score that's actually actionable

A churn score only earns its keep if it points at a playbook. A model that returns a number between 0 and 1 and stops there is a science project. The scoring query below is the shape that keeps working — straightforward SQL, transparent weights, outputs a category the CSM dashboard can actually filter on.

-- Churn risk score — simple, transparent, fits in a materialized view
-- Refresh nightly. Score points at a named playbook, not a probability.
with usage as (
  select
    account_id,
    count(distinct date_trunc('day', occurred_at)) filter (
      where occurred_at > now() - interval '30 days'
    ) as active_days_30d,
    count(distinct date_trunc('day', occurred_at)) filter (
      where occurred_at > now() - interval '60 days'
        and occurred_at <= now() - interval '30 days'
    ) as active_days_prior_30d,
    count(distinct event_type) filter (
      where occurred_at > now() - interval '30 days'
    ) as feature_breadth_30d
  from events
  group by account_id
),
billing as (
  select
    account_id,
    bool_or(status = 'past_due') as has_past_due,
    min(card_exp_month || '-' || card_exp_year) as next_card_exp
  from subscriptions
  where status in ('active', 'past_due')
  group by account_id
),
tickets as (
  select
    account_id,
    count(*) filter (
      where created_at > now() - interval '30 days'
    ) as tickets_30d
  from support_tickets
  group by account_id
)
select
  u.account_id,
  -- Component signals
  case when u.active_days_prior_30d > 0
       and u.active_days_30d <= u.active_days_prior_30d * 0.5
       then 3 else 0 end as login_drop_pts,
  case when u.feature_breadth_30d <= 2 then 2 else 0 end as breadth_pts,
  case when t.tickets_30d >= 3 then 2 else 0 end as ticket_pts,
  case when b.has_past_due then 4 else 0 end as billing_pts,
  -- Total + bucketed category
  (case when u.active_days_prior_30d > 0
        and u.active_days_30d <= u.active_days_prior_30d * 0.5 then 3 else 0 end
   + case when u.feature_breadth_30d <= 2 then 2 else 0 end
   + case when t.tickets_30d >= 3 then 2 else 0 end
   + case when b.has_past_due then 4 else 0 end) as risk_score
from usage u
left join billing b using (account_id)
left join tickets t using (account_id);

Bucket the score into three categories — green, amber, red — and wire each bucket to a playbook. Green gets the usual lifecycle emails. Amber gets a lightweight in-app nudge and a CSM task. Red gets a named human, an outreach within 48 hours, and a weekly touch until the account moves out of red. A score without a playbook is decoration.

Cohort retention, done properly

Blended retention metrics — the single number on the executive dashboard — hide more than they reveal. The 92% monthly retention figure for a growing business can mask a product where the oldest cohorts are collapsing because the newest, largest cohorts drag the average up. Cohort retention fixes this by grouping customers by signup month and tracking each cohort independently.

  • Build retention tables with signup cohort on the rows, months-since-signup on the columns. The diagonal tells the truth; the bottom-right is the future.
  • Track the D7, D30, and D90 retention for each cohort. 60–70% of annual churn happens in the first 90 days, so the early cells are where most of the signal lives.
  • Break cohorts out by acquisition channel, plan tier, and onboarding-flow variant. Averaging across all of them is how product-market fit problems get hidden.
  • Don't forget survival curves. A flat retention line after month three is the shape that pays for a company; a line that keeps declining after month six means the product has a leak it isn't catching.

Survivorship bias is the trap that eats most churn analyses. A retention report built only from 'active customers last quarter' is selecting on the outcome. Every cohort analysis should include the users who churned — otherwise the numbers describe the survivors, not the population.

Dunning — the involuntary churn lever

Dunning is the unglamorous operational work that recovers 30–50% of failed payments for teams that invest in it properly. The pattern that keeps working: retry intelligently, communicate through multiple channels, make the update path one click, and know when to give up before the relationship sours.

A dunning schedule that recovers

  1. Day 0 — retry on the same payment method. Network-declined is often transient.
  2. Day 1 — email the account admin with a direct, single-click update link. Short subject, no marketing copy.
  3. Day 3 — in-app banner on the next login. 'Your last payment didn't go through' with a single button.
  4. Day 5 — retry on card. Stripe Smart Retries and equivalents time these based on when the bank is most likely to approve.
  5. Day 7 — second email, different subject line, acknowledges the first one didn't work.
  6. Day 10 — final retry, downgrade-warning email. Calendar a CSM outreach for enterprise accounts.
  7. Day 14 — soft downgrade to read-only or free tier. Do not hard-delete data; recovery rates on reactivations depend on it.

The single-biggest dunning win is updating card details before the decline happens. Cards expiring in the next 30 days get an in-app prompt on every login and a one-click update flow. Teams that ship this pull involuntary churn down by a third before touching retries.

Winback — the cheapest customers to close

Winback campaigns target customers who have already cancelled. They convert at higher rates than cold outbound because the prospect already knows the product, already knows the price, and has a specific reason they left. The reason is what the campaign needs to address — a generic 'we miss you' email is the lowest-performing variant in the category.

  • Segment by cancellation reason. 'Too expensive' gets a different winback than 'missing a feature'. If the cancellation survey is one open-text field, the winback campaign can't personalize and the reply rate collapses.
  • Time the first outreach three to six months after churn, not three days. The user needs distance before they're willing to re-engage.
  • Lead with what changed. If a missing feature got shipped, say so. If the pricing is the same, don't pretend it isn't — offer a discount or a grandfathered tier explicitly.
  • Measure winback as a first-class funnel, not a footnote. Cost-to-reactivate is often an order of magnitude lower than cost-to-acquire new, and most teams don't report it separately.

Instrumenting the churn program

A churn program that isn't instrumented regresses. The numbers that belong on the weekly dashboard: gross churn split voluntary/involuntary, net revenue retention (NRR), cohort retention at D7/D30/D90, involuntary recovery rate, winback conversion rate, and churn-risk-score distribution. NRR above 110% is the shape that compounds without acquisition; below 90% is a leak that acquisition can't keep up with forever.

Key takeaways

  • Split voluntary and involuntary churn from day one. The fixes live in different parts of the org.
  • Leading indicators — login drop, breadth narrowing, ticket spikes — give 30–60 days of lead time that post-hoc dashboards don't.
  • A churn risk score only earns its keep if each bucket points at a named playbook.
  • Cohort retention beats blended retention. Survivorship bias is the trap that eats most analyses — always include the users who left.
  • Dunning and winback are the two highest-ROI retention investments for most SaaS teams. They're unglamorous and they compound.
#churn#retention#cohort-analysis#dunning#saas-metrics#analytics
Working on something similar?

Let's build it together.

We ship production SaaS, marketplaces, and web apps. If you want an engineering partner — not a consultancy — let's talk.