Skip to content
Back to Monetization & Revenue

Dunning Management

How to recover failed subscription payments through a dunning sequence that maximizes recovery without alienating users.

Why

Involuntary churn — when a subscription fails because a card expired or was declined, not because the user chose to cancel — accounts for 20-40% of total churn in most SaaS. These are users who wanted to keep paying you but could not, and a good dunning sequence recovers 50-70% of them. The economics are exceptional: a recovered $29/mo subscriber is worth $348 of ARR for the cost of 3 emails and a retry. The mistake is either giving up too early (one retry then cancel) or being too aggressive (daily emails that make the user feel harassed and cancel for real). The right cadence is 3-4 retries over 14 days with smart retry timing (retrying on day 3, 7, 14 after the failure), each with a clear 'update your card' link and a grace period that keeps the user on the plan during recovery.

When

When you have any subscription product. Configure the dunning sequence before launch — adding it after you have already lost users to failed payments is too late.

How

1. Configure Stripe's Smart Retries (Billing settings → Smart retries) — Stripe uses ML to pick retry times with the highest success probability, recovering ~9% more than fixed retries
2. Set a grace period of 7-14 days during which the user keeps access while retries run — canceling access on first failure kills recovery
3. Write a 3-email dunning sequence: Email 1 (day 0, friendly 'your card was declined'), Email 2 (day 5, 'final notice' tone), Email 3 (day 12, 'your subscription will cancel in 2 days')
4. Each email must have a one-click 'update card' link to the Stripe Customer Portal — do not make the user log in and navigate
5. On the final retry failure, cancel the subscription but keep the user's data for 30 days so they can resubscribe without losing history
6. Track recovery rate by cohort (card type, failure reason, geo) — declines due to 'insufficient funds' recover worse than 'expired card', and segmenting tells you where to intervene
7. For high-value customers (> $500/mo), add a manual step: have customer success email personally before the final cancel
8. A/B test the email copy and timing — moving the second retry from day 5 to day 3 can lift recovery 5-10%

Example

# Stripe dunning config (via API)
stripe.subscriptions.update("sub_123", {
  days_until_due: 14,        # grace period
  billing_cycle_anchor: "now",
});

# Email sequence (Resend + React Email)
const dunningEmails = [
  { day: 0,  subject: "Your card was declined", tone: "friendly" },
  { day: 5,  subject: "Action needed: update your card", tone: "urgent" },
  { day: 12, subject: "Final notice — subscription cancels in 2 days", tone: "final" },
];

# On invoice.payment_failed webhook
async function onPaymentFailed(invoice) {
  const attempt = invoice.attempt_count;
  if (attempt === 1) await sendEmail(invoice.customer, dunningEmails[0]);
  if (attempt === 3) await sendEmail(invoice.customer, dunningEmails[1]);
  if (attempt === 4) {
    await sendEmail(invoice.customer, dunningEmails[2]);
    await scheduleCancel(invoice.subscription, { delayDays: 2 });
  }
}

Common Problems

  • ⚠Canceling access immediately on first payment failure — the user's card expired and they are on vacation; you cancel their access and they resubscribe to a competitor. Always grant a grace period.
  • ⚠Sending dunning emails from a no-reply@ address — the user replies to ask why their card was declined and gets a bounce, then charges back. Use a monitored inbox or a support ticket link.
  • ⚠Not distinguishing involuntary from voluntary churn — your churn dashboard shows 30% churn but 10 points are recoverable dunning failures. Segment them or you optimize the wrong thing.

Best Practices

  • ✓Enable Stripe Smart Retries and let Stripe pick the retry times — its ML model is trained on billions of retries and beats any fixed schedule you can devise.
  • ✓Keep the user's data for at least 30 days after cancel — a returning user who finds their projects deleted has zero reason to resubscribe, and you have lost the LTV entirely.
  • ✓Measure dunning recovery as a first-class metric alongside churn — 'involuntary churn rate' should be on the same dashboard as voluntary churn, with a target of < 2% of MRR.