The most recoverable churn in SaaS
Involuntary churn — subscribers who lose access because a payment failed, not because they decided to leave — accounts for 20–40% of total churn for most SaaS businesses. Unlike voluntary churn (where the customer has made a decision), involuntary churn is almost entirely recoverable with the right dunning sequence.
Without a dunning system, the typical outcome is: Stripe declines the card, access pauses (or continues on a grace period), no communication is sent, the customer assumes their subscription is active, and they’re surprised when they get locked out. By the time they notice, frustration has replaced any intention to update their card. The subscription lapses.
With structured dunning: 40–65% of failed-payment subscribers recover, typically within the first 3 days of the sequence. The customers who don’t recover were leaving anyway.
How it works in GHL
Trigger: Stripe fires a payment_intent.payment_failed or invoice.payment_failed webhook → webhook hits GHL via Zapier/Make relay → GHL creates a payment_failed tag on the contact → 14-day dunning workflow begins.
The 14-day dunning sequence:
| Day | Channel | Message framing |
|---|---|---|
| 0 | Helpful service notice. Warm tone: “We weren’t able to process your payment — here’s a quick fix.” Direct billing update link. | |
| 0+5min | SMS | Short, direct: “Hi [Name], your [product] payment didn’t go through. Update here: [link]“ |
| 3 | Friendly reminder. “Just checking in — account access continues through day 7. Takes 30 seconds to update.” | |
| 7 | Email + SMS | Final warning before access pause. “Your account access pauses in 3 days. Here’s a direct link to update your billing info.” |
| 10 | Account paused notification. Tone shifts to re-activation framing: “Your account is paused — restore it in 2 clicks.” | |
| 14 | Final recovery attempt. “Your account closes in 48 hours — here’s a one-click restore.” Optional save offer for high-value accounts. |
Critical detail: Every email includes a direct, deep-linked billing update URL — not “log in and navigate to Settings > Billing.” A direct Stripe Customer Portal link (/billing/portal) or Chargebee self-serve payment update page. Friction in the recovery path is the primary reason dunning sequences fail. Each additional click between the email and the payment update form loses ~20% of recovery intent.
Resolution handling
When payment is recovered — Stripe fires invoice.paid or the customer updates their payment method — GHL immediately:
- Tags the contact
payment_recovered. - Removes
payment_failedtag. - Cancels all pending dunning emails (no “your account pauses in X days” after recovery).
- Sends a confirmation email: “All good — your payment went through and your account is fully restored.”
- Logs the recovery in a
Dunning Recoverypipeline for MRR tracking.
Resolution fires on the Stripe event, not on the email click. If the customer updates their card directly through Stripe’s portal without clicking your email link, the invoice.paid webhook still cancels the dunning sequence.
Stripe event → GHL action map
| Stripe event | GHL action |
|---|---|
invoice.payment_failed | Tag payment_failed, start 14-day dunning workflow |
customer.updated (payment method changed) | Cancel dunning, send recovery confirmation |
invoice.paid after prior failure | Cancel dunning, send recovery confirmation, log recovery in pipeline |
customer.subscription.deleted (confirmed churn) | Remove dunning tag, add churned_involuntary tag, start win-back sequence |
| Day 10 in sequence, no recovery | Move to “account paused” pipeline stage |
| Day 14, no recovery | Close dunning, tag involuntary_churn, start 30-day win-back sequence |
ROI math: what dunning is actually worth
Acme Inc — $120k MRR, 2.5% monthly involuntary churn rate (no dunning), $240 ARPA.
Monthly involuntary churn: $120k × 2.5% = $3,000 MRR lost monthly to failed payments.
Without dunning: zero recovery. Annual involuntary churn cost: $36,000 in lost MRR.
With 14-day dunning deployed:
- Recovery rate: 50% of failed-payment subscribers (industry average with structured dunning).
- Monthly recovery: $3,000 × 50% = $1,500 MRR recovered monthly.
- Annual recovered MRR: $18,000.
At a one-time cost of $1,200 for the SaaS Snapshot, payback period: less than 3 weeks.
For Northwind SaaS ($50k MRR, 3% involuntary churn, $199 ARPA):
- Monthly failed-payment MRR: $1,500. 50% recovery = $750/month, $9,000/year recovered.
Works with Chargebee, Recurly, and Paddle
The snapshot is built with Stripe as the primary integration. The same dunning pattern works with Chargebee (native retry logic + webhook events), Recurly (invoice.past_due and invoice.paid events), and Paddle (subscription.payment_failed). The GHL-side automation is billing-provider-agnostic — configure the webhook source to match your provider.
Stop losing subscribers to failed payments — dunning live in 24 hours
Should I pause account access immediately on payment failure or wait?
Best practice is a 7-day grace period before pausing access. Immediate suspension on day 0 triggers a panic response and increases voluntary cancellations — customers who would have updated their card instead decide it's not worth the hassle. The snapshot's default grace period is 7 days: access continues, the sequence runs, and access pauses only if payment hasn't been recovered by day 7.
What if the customer updates their payment method through the Stripe portal directly?
Resolution handling is event-driven, not click-driven. If the customer logs into Stripe's Customer Portal directly (without clicking your email link) and updates their card, Stripe fires the `invoice.paid` event. GHL receives it via webhook and cancels all pending dunning emails immediately. You never send a 'your account closes in 48 hours' email to someone who already fixed their billing.
Can I offer a save discount inside the dunning sequence for high-value accounts?
Yes — the snapshot's day-14 email includes a conditional branch: if the contact's MRR value exceeds a threshold (e.g., $500/month), the email includes a 1-month payment pause offer or a temporary discount code. For accounts below threshold, the standard recovery CTA fires. Configure the threshold in the workflow branch condition — no code required.
How do I track dunning recovery as a metric separate from overall churn?
The snapshot includes a 'Dunning Recovery' pipeline in GHL with stages: Payment Failed → Recovering → Recovered → Confirmed Churn. Every failed-payment contact enters this pipeline. Recovered contacts close the pipeline stage as 'won.' This gives you a clean monthly report: failed-payment MRR entered vs recovered MRR, which is your dunning recovery rate — a metric you can track over time and optimize.