hose Demo data with a pulse

A claim about Quenchly

One invoice in twelve fails on the first attempt. Dunning recovers about half.

First-attempt failure between 5% and 11% of invoices. The retry ladder at days 1, 3, 5 and 7 recovers 40% to 65% of them. Most of the rest are paid two to four weeks later when the customer updates the card, and the remainder become payment-failure cancels.

holds on the current window

as of moments ago

Invoice outcomes

WITH first_try AS (
  SELECT invoice_id, MIN(at) AS first_at
  FROM payments GROUP BY invoice_id
),
outcome AS (
  SELECT p.invoice_id,
         MAX(CASE WHEN p.at = f.first_at AND p.outcome = 'decline' THEN 1 ELSE 0 END) AS failed_first,
         MAX(CASE WHEN p.outcome = 'success'
                   AND julianday(p.at) - julianday(f.first_at) <= 8 THEN 1 ELSE 0 END)  AS paid_in_ladder,
         MAX(CASE WHEN p.outcome = 'success'
                   AND julianday(p.at) - julianday(f.first_at) > 8 THEN 1 ELSE 0 END)   AS paid_late,
         COUNT(*)                                                                      AS attempts
  FROM payments p
  JOIN first_try f USING (invoice_id)
  JOIN invoices  i ON i.id = p.invoice_id
  -- Invoices from the last two weeks may still be mid-ladder.
  WHERE datetime(i.issued_at) < datetime((SELECT MAX(issued_at) FROM invoices), '-14 days')
  GROUP BY p.invoice_id
)
SELECT COUNT(*)                                                                    AS invoices,
       ROUND(100.0 * SUM(failed_first) / COUNT(*), 1)                              AS first_attempt_failure_pct,
       ROUND(100.0 * SUM(CASE WHEN failed_first = 1 AND paid_in_ladder = 1 THEN 1 ELSE 0 END)
                   / SUM(failed_first), 1)                                          AS recovered_in_ladder_pct,
       ROUND(100.0 * SUM(CASE WHEN failed_first = 1 AND paid_in_ladder = 0 AND paid_late = 1 THEN 1 ELSE 0 END)
                   / SUM(failed_first), 1)                                          AS recovered_late_pct
FROM outcome;
invoices
15506
first_attempt_failure_pct
7.8
recovered_in_ladder_pct
52.9
recovered_late_pct
31.5

holds on the current window

Retry ladder cadence

WITH first_try AS (
  SELECT invoice_id, MIN(at) AS first_at FROM payments GROUP BY invoice_id
)
SELECT CAST(ROUND(julianday(p.at) - julianday(f.first_at)) AS INTEGER) AS days_after_first,
       COUNT(*) AS attempts
FROM payments p JOIN first_try f USING (invoice_id)
WHERE p.at > f.first_at
GROUP BY 1 ORDER BY 1;
days_after_firstattempts
11230
31089
5916
7713
1425
1515
1626
1726
1829
1917
2022
2117
2226
2323
2421
2529
2626
2729
2814
2918
3017

holds on the current window

Involuntary churn is roughly a quarter of all SaaS churn in the published benchmarks, and it is invisible in most demo data because payments are modeled as one boolean. Quenchly records every attempt. A declined card walks a retry ladder at one, three, five and seven days. Some retries succeed and the invoice is paid late. When the ladder runs out, most customers update the card within a few weeks and a sixth attempt succeeds. The rest are written off as uncollectible and the subscription cancels with reason = 'payment_failure'. A billing provider records exactly that.

What you should see

One row, with a first-attempt failure rate in the high single digits and a recovery rate above half, because the recovery figure here counts any later success, card updates included. The cadence query returns the four ladder days at 1, 3, 5 and 7 with counts shrinking down the ladder, then a scatter of late attempts between days 14 and 30: the card updates. Drop the two-week exclusion and the recovery rate falls slightly, because recent failures have not finished retrying yet. That is right-censoring, and it is deliberate.

Run it yourself

More on Quenchly