Definition

How to calculate a failed-payment recovery rate

Failed-payment recovery rate is the share of invoices that failed on the first attempt and were later paid. Compute it as recovered divided by recovered plus lost, and leave out invoices still in retry. Otherwise this month's failures pull the rate down for no good reason. Here are the exact rules and the traps.

What is a failed-payment recovery rate?

It answers one question: of the invoices where the first charge attempt failed, how many did you eventually collect? An invoice that paid on the first try is not part of it. An invoice that failed and was paid after a retry or after the customer updated the card counts as recovered.

It is a rate of outcomes, and it tells you how good your whole recovery process is: Stripe's retries, your emails, and the customer's own behaviour. It does not tell you which part works.

How do I decide which invoices belong in it?

I use this definition for a failed first payment: the invoice was attempted, the amount due is above zero, it is not a draft, and either the attempt count reached two or the invoice is not in paid status. Then I sort each one into three outcomes:

The 30-day cut is a judgment call, like the 45-day window I use for cancellations. It is wide enough to let slow retry schedules finish. If yours are slower, widen it and note that you did.

What is the formula?

Recovery rate equals recovered divided by recovered plus lost, among invoices that are no longer in retry. The in-retry invoices are excluded from both sides, because nobody knows their fate yet.

I report it by count, and I keep the value in dollars beside it. A recovery rate of 60% means something different on a $9 plan than on a $900 plan, and a few large invoices can swing the dollar rate while the count stays flat.

Why exclude the invoices still in retry?

Because they would drag the rate down in the current month. A card that failed on Monday is not a lost invoice on Tuesday. If you include it as unrecovered, your rate always looks worst for the latest weeks, and you will think a change you made last week made things worse.

The cost of excluding them is that the rate is conservative about the present: it says nothing about the newest failures. That is a fair trade, and I state it on the method page of the report.

How does it relate to involuntary churn?

Closely, and you must not double count. If a failed invoice ended in a cancelled subscription, I count its value under involuntary churn and not as a lost payment. The two buckets together answer "what did card failures cost me," and each dollar appears once.

The rules for the churn side are in what involuntary churn is. For the recovery side, with the steps for improving it, read how to recover failed payments on Stripe subscriptions.

What would 0% or 100% mean?

Almost certainly a data problem. A recovery rate of exactly 0% suggests invoices are never retried, or the key lacks a permission. A rate of 100% suggests invoices are being marked paid outside the normal flow. Before I send a report I look for both, and I ask the customer if either shows up. A missing permission fails the run with an error, it does not return zeros, but a real 0% is worth a conversation.

The same caution applies to very small accounts. With fewer than about 30 events in a bucket, a rate is direction, not a result.

What did it look like in the synthetic sample?

My sample report is a fictional company, Lumenfold Analytics, with data I generated so the answer is known. In it, 674 invoices failed on the first attempt, 364 were recovered, 79 were lost and 28 were still in retry, worth $1,598. The top decline codes were card_declined, generic_decline and expired_card. None of that is real. It is there to show the layout, and I would not compare your account to it.

Open the sample report to see how the recovery rate and those counts sit next to the dollars.

How do I know my changes improved it?

A before-and-after comparison is weak evidence, since seasons, price changes and customer mix also move the rate. A holdout is better: leave a random share of customers out of the new messages and compare both groups on the same definition. In my pilot that share is 20%, picked by a stable hash of the customer id. I explain why in what a holdout group is.

What can Stripe not show me here?

Recoveries that happened through a channel it does not see. If a customer was brought back by an email from another tool or a support conversation, Stripe shows only that the invoice was paid. That is fine for the rate, but it means you cannot tell which of your efforts worked from Stripe data alone.

It also cannot show the value after coupons: invoices use the amount due, and plan values use list price. State that when you quote the number.

Do I need a tool to compute it?

For a small account, a spreadsheet export of invoices is enough. Once there are thousands of invoices, the counting is the slow part. The Revenue Leak Report computes it for $490 from a restricted read-only Stripe key, within 48 hours of my having the key.

Want your own numbers?

The Revenue Leak Report puts failed payments, unconverted trials, cancellations and downgrades in dollars per month, read from a restricted read-only Stripe key. $490, delivered within 48 hours of receiving the key. Nothing in your account is changed.

Get the Revenue Leak Report - $490 See a sample (synthetic data)