All articles
4 min read •

Measure Your Involuntary Churn Before You Try to Fix It

How to compute what failed Stripe payments actually cost you — the exact query, the four decline categories that behave differently, and why your dashboard churn number hides the recoverable part.

Involuntary churn is revenue you lost from customers who never decided to leave. Their card expired, their bank declined the charge, their limit was reached. They still want the product. The subscription ended anyway.

Most SaaS dashboards do not separate this from voluntary churn, which means the number is invisible in the place founders look for it. Before evaluating any recovery tool, compute yours. The figure determines whether this is a problem worth ten minutes or a problem worth a budget line.

The number that matters is not a rate

Churn rate is the wrong unit for this decision. You are not deciding whether your churn is good or bad in the abstract; you are deciding whether to spend money recovering a specific dollar amount.

Recoverable monthly revenue  =  Σ (failed invoice amounts in the period)
                              ×  the fraction that is recoverable
                              ÷  months in the period

The first term is a query. The second is the part everybody guesses at, and the part that varies most between accounts.

Pulling the raw figure from Stripe

Ninety days is the right window: long enough to smooth out a bad month, short enough to reflect your current customer mix.

Using the Stripe CLI:

stripe invoices list \
  --status=open \
  --created "gt=$(date -d '90 days ago' +%s)" \
  --limit 100 \
  --expand data.charge

Or against the API, iterating pages and summing amount_due on invoices where attempt_count > 0 and status is open or uncollectible. Two adjustments matter:

Exclude invoices that later succeeded. An invoice that failed on attempt one and cleared on attempt three is not lost revenue — Stripe's own retries already recovered it. Counting it inflates your number and will make any recovery tool look better than it is.

Count the subscription, not the invoice. A customer who churns on a failed $200 invoice does not cost you $200. They cost you $200 per month for however long they would have stayed. If your median customer lifetime is 14 months and they churn at month 6, the failed invoice represents roughly eight months of forward revenue. Whether to model it that way depends on how you make budget decisions, but be explicit about which number you are using — the two differ by an order of magnitude and both get quoted as "involuntary churn."

The four decline categories, which behave nothing alike

The fraction of your failed volume that is actually recoverable depends almost entirely on why the charges failed. Stripe exposes this on the charge's outcome.reason and decline_code.

CategoryTypical decline codesWhat it meansResponds to
Expired or replaced cardexpired_card, incorrect_numberCustomer still wants the product, the credential is staleEmail asking for an update — the highest-recovery category
Temporary funds issueinsufficient_fundsTiming, not intentRetry timing plus a reminder; recovers moderately
Issuer risk declinedo_not_honor, generic_declineBank-side, often opaqueRetry at a different time; a different card usually works
Hard declinelost_card, stolen_card, fraudulentDo not retryNothing. Excluding these from your denominator is not pessimism, it is accuracy

Two accounts with identical failed-payment volume can have completely different recoverable amounts depending on this mix. This is why vendor recovery-rate benchmarks are close to useless for forecasting: they describe someone else's distribution.

Break your 90-day total down by category before assuming any recovery percentage.

What your existing Stripe setup already recovers

Before attributing anything to a new tool, establish the baseline. Stripe's Smart Retries already reattempt failed charges on an ML-optimised schedule, and Stripe can send its own failed-payment emails if that setting is enabled. Whatever those recover is not incremental.

The number you want is the residual: failed invoices that Stripe's own retry window exhausted without recovering, filtered to the categories above that respond to customer contact. That residual is the entire addressable market for any dunning layer, yours or a vendor's.

Sanity-checking a vendor's projection

Once you have your own figure, vendor claims become checkable. Ask for the three inputs behind any projected recovery: the decline-category mix it assumes, the baseline it measures incremental lift against, and whether "recovered" means the invoice was paid or merely that the customer clicked.

A projection that cannot decompose into those three inputs is a benchmark wearing a forecast's clothes.

The subscription-status decision, while you are in there

One Stripe setting is worth checking during this exercise: what happens when the retry schedule is exhausted. The default sends the subscription to canceled. Setting it to unpaid instead leaves the subscription intact but unusable, preserving the record and letting your communication sequence continue past Stripe's retry window before you make the cancellation decision yourself.

A cancelled subscription is a harder thing to recover than an unpaid one, for reasons that are as much psychological as technical.


Or skip the query. PaidGuard connects to your existing Stripe account read-only, audits the last 90 days of failed payments, and shows you the figure — broken down by decline category — before you enter a card. If the number is small, you will know in five minutes and you should not buy anything. $39/month plus 5% of revenue actually recovered, first month free.

Related: Evaluating Stripe dunning software · Building dunning on invoice.payment_failed

Sources: Stripe — automatic collection and Smart Retries

measure involuntary churnstripe failed payments revenue lossinvoluntary churn rate calculationhow much am I losing to failed payments

Want to stop losing revenue to failed payments?

See what failed payments have cost you over the last 90 days — free, read-only, no card required.

See my number free →