
When a payment fails, most SaaS tools do one thing: retry.
But I've been thinking about this differently.
There are exactly two types of failed payments:
The card is fine. The customer has money.
They just need to be charged at the right moment.
Stripe's smart retry works here.
No amount of retrying will ever recover these.
The card is gone. Someone has to tell the customer.
Retries alone won't work — outreach is the only path.
The mistake most founders make is treating both the same.
One email sequence. Same retry cadence. For every failure.
But an expired card and an insufficient funds failure need completely different responses.
DunnAI reads the decline code behind every failure, classifies it into the right bucket, and reaches out in your product's own voice - only when outreach is actually the answer.
Free until $49 is recovered.
Curious if others have thought about this split.
What's your current approach to failed payments?
Full disclosure: I'm Avery Lin (avrlin). I've been packaging a small Stripe Dunning Email Pack (failure-reason matrix → day-0/3/7 copy + Customer Portal CTA) with AI assistance, so take this as adjacent interest, not neutral advice.
The two-bucket split you describe is exactly where generic dunning breaks: Smart Retries help NSF/network timing issues, but expired_card / do_not_honor need a human-sounding day-1 ask to update the card — another retry just burns goodwill. Branching the first email by decline family is the boring fix that recovers the easy ones without sounding like a bug ticket.
Curious — when you classify failures, do you treat do_not_honor as soft Bucket 2 (gentle outreach + one retry) or hard Bucket 2 (outreach only)?