how to build a dunning email sequence for failed subscription invoices
A playbook for building a webhook-driven dunning email sequence for failed subscription invoices: cadence, per-email content, the single call to action, and the halt-on-payment gate. Use when smart retries alone do not recover revenue and failed invoices need customer-facing outreach. Not for pre-renewal reminders, marketing emails, or third-party dunning tools that own the sequence.
TL;DR
A good dunning sequence is 4 to 5 emails over about three weeks: a friendly heads-up on day 1, a firmer nudge around day 5, an urgent warning around day 12, a final notice around day 20, and a service-paused notice if it comes to that. Trigger each email off invoice.paymentfailed, gate every send on the invoice still being unpaid, and halt the whole sequence on invoice.paymentsucceeded. Every email has exactly one call to action: update the payment method.
The query
how to build a dunning email sequence for failed subscription invoicesUse this when
- Failed invoices need customer outreach beyond automatic retries
- Payment retries recover the easy cases but revenue still leaks
- Dunning emails go out manually, late, or not at all
- You need a webhook-driven sequence that stops the moment the customer pays
Not for
- Pre-renewal or upcoming-invoice reminders (different sequence, different tone)
- Failures that need 3D Secure authentication (the email must carry an auth link, different content)
- Teams using a third-party dunning tool that owns the sequence
Steps
1. Fix the cadence before writing a single email
Day 1: friendly heads-up. Day 5: firmer reminder with the amount. Day 12: urgent warning that service is at risk. Day 20: final notice with the exact pause date. Day 21+: service paused or account canceled notice. Write the timeline down first; content comes second.
Expected output: a fixed day-by-day schedule everyone agrees on before any code is written.
2. Trigger email 1 on invoice.payment_failed
Fire the first email the moment the invoice fails. Include the amount, the failed reason in plain language (not the raw decline code), and a direct link to update the payment method.
Expected output: the customer knows what failed, how much, and exactly how to fix it within minutes of the failure.
3. Gate every send on the invoice still being unpaid
Before each email goes out, check the invoice status. On invoice.payment_succeeded, halt the sequence immediately. Nothing kills trust like a dunning email arriving after the customer paid.
Expected output: paying customers never receive another dunning email.
4. Personalize the reason line per decline code
insufficientfunds gets empathy ("your bank declined the charge - this happens"), donothonor gets "try a different card or call your bank," expiredcard gets the obvious. Generic templates convert worse than reason-specific ones.
Expected output: open and fix rates beat the old generic template.
5. Give every email exactly one call to action
The link to update the payment method. No upsells, no newsletter links, no "visit your dashboard" detours. Every extra link dilutes the fix rate.
Expected output: each email has one prominent button and nothing else competing with it.
6. Run smart retries in parallel, not instead
Let the payment provider's smart-retry logic keep attempting the charge on its own schedule. The emails and the retries are independent recovery channels; measure each separately.
Expected output: recovery attribution shows which channel recovered which invoices.
7. Measure recovery per step and prune
Track what fraction of failed invoices each email step recovers. Rewrite or drop steps that never convert; add a step only if the data says there is a gap.
Expected output: the sequence earns its sends with data instead of tradition.
Variant phrasings
dunning email best practices saas
Same playbook. The non-negotiables: one CTA, halt-on-payment, reason-specific copy.
failed payment email sequence template
Steps 1 through 5 are the template: cadence, trigger, gate, reason line, single CTA.
how many dunning emails to send before canceling
Four to five, per step 1. Past that you are training customers to ignore you.
Why it happens
Most failed payments are fixable by the customer: expired card, insufficient funds today, a bank challenge that needs a tap. But the customer has to know about it and has to have a one-click path to fix it. Retries alone recover the easy cases where the card just works on attempt three; the email sequence recovers everyone who needs a nudge and a link. Without it, the invoice sits unpaid until someone manually chases it, usually nobody.
Edge cases
- Suppress dunning for customers already in a support conversation about the same invoice: the agent handling it owns the communication.
- Expired trial conversions fail differently than renewals: the customer may not know they were ever going to be charged. Soften email 1.
- Annual invoices: one failed annual charge deserves a phone call, not just email 3. Escalate the channel for high-value invoices.
- Do not dunning a customer whose subscription was already canceled: gate the sequence on subscription status, not just invoice status.
- Localize the reason line; a translated plain-language explanation beats the raw decline code in every market.
- If the billing email bounces, the sequence is dead: fall back to the account owner or an in-app banner.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_sif9o6M9CH2HpNH6zDsGvw
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.