Stripe Smart Retries vs Custom Dunning, in Plain English
What Stripe's built-in Smart Retries does well, where it falls short, and when an operator should keep it on, replace it, or run both. From a founder building a dunning tool, not a Stripe insider.
I'm Yarin. I'm building RecoverStack, a flat-fee dunning tool for bootstrapped SaaS on Stripe. While I was figuring out where the product fits, I had to read a lot of Stripe's documentation on Smart Retries (their built-in retry feature) and decide what I'm offering value on top.
Most operator-facing comparisons of Smart Retries vs custom dunning are written by vendors trying to sell custom dunning, including my own. I want to do this one with the bias declared up front, and try to be as honest as possible about where Smart Retries is genuinely the right answer for operators.
What Smart Retries actually is
Stripe's Smart Retries is a feature inside Stripe Billing that picks retry timing for failed subscription charges. You can enable it in the Stripe dashboard under Settings → Subscriptions and emails → Manage failed payments. There are no code changes required.
Behind the scenes, it's an ML model trained on Stripe's billions of historical transactions. The model picks a retry time it thinks is most likely to succeed, given the failure context (decline code, time of day, day of week, recent retry history on similar cards, and so on). Stripe doesn't expose the model internals, so I'm taking the description from their public documentation.
Stripe used to publish a head-to-head benchmark: businesses using Smart Retries recover 9% more revenue than those retrying failed payments on a set schedule (archived from April 2026). They've since removed it from their Billing page along with the recovery aggregate data. What they currently publish is that Stripe recovered $8.2B in failed payments in 2025 across all their recovery tools combined, which includes Smart Retries + the automatic card updater + the basic failed-payment email, and still no per-decline-code breakdown. For a meaningful number of operators, that stock toolkit is the right place to stop.
What Smart Retries does well
It's free: Smart Retries is included in standard Stripe processing fees. There is no incremental cost to turn it on.
It works without code: Toggle it on, and Stripe handles the rest. For a founder who hasn't built any dunning logic, this is a one-minute setup that immediately moves recovery rates up from whatever a naive 3-day fixed retry algo was producing.
The retry timing is reasonable: I've dug through enough public Stripe engineering posts to be reasonably confident that the timing isn't random. The model considers card-issuer behavior patterns, transient-failure recovery curves, and (I think) some signal about when a customer's usual paydays might be. For straightforward processing_error and bank-block cases, it's a perfectly adequate retry strategy.
It plays well with Stripe's other recovery features. Smart Retries coordinates with Stripe's automatic card updater so retries happen with refreshed card data when available. If you enable both, you get a better recovery rate than either alone.
Where Smart Retries falls short
These are the structural limits I keep running into when I think about what Smart Retries can and can not do.
It treats every failure as a retry problem
This is the big one. Smart Retries always tries to retry. For decline codes where retrying will never succeed (expired_card, lost_card, incorrect_cvc, etc., which I went through in detail in the decline-codes guide), each retry attempt is a wasted day during in which the customer could have been emailed and could have updated their card. One carve-out: Stripe's card account updater can silently refresh expired or reissued cards behind the scenes, and Stripe executes the held retries once a new payment method lands. So "never succeeds on retry" applies to the cases where the updater didn't have the new card, which is exactly when the customer email is the only path left.
Stripe's recommended default retry window is 8 tries within 2 weeks, configurable from 1 week up to 2 months. For a card-update-required failure, that's 2 weeks of zero recovery probability on the default setting. The recovery curve (how recovery rate falls as elapsed time increases) is fairly steep, so those weeks have a real cost.
It doesn't email the customer
Smart Retries operates entirely on the payment rails. It retries the charge, and that's it. Stripe does offer a separate "failed payment emails" toggle, which sends a single generic email after the retries exhaust, but it isn't a multi-step sequence and it isn't branched on the decline code.
My working estimate is that somewhere between 30% and 40% of decline codes by volume require customer action (give us a new card, contact your bank, switch payment methods). For all of those, retries don't do anything useful, and the customer never knows there's a problem until product access gets revoked.
It runs as a black box
You can't see what Smart Retries is doing as it's doing it. The Stripe dashboard shows retries-attempted and retries-succeeded for an invoice, but it doesn't tell you:
- Why a specific retry was scheduled for a specific time.
- Which customer charges are about to be retried in the next hour.
- What the projected recovery rate is for the current at-risk MRR.
- Which decline codes Smart Retries is currently doing well or poorly on, in your specific account.
For an operator who wants to intervene proactively (manually reach out to a customer, pause retries on a specific subscription, prioritize the high-MRR at-risk customers), the visibility is really missing.
You can't tune it
Smart Retries is on or off. There's no per-decline-code configuration, no per-customer override, no way to say "skip retries entirely on expired_card for our customer base, because we've found the email-first flow recovers more." If you have an opinion about your specific customer base, Smart Retries can't take it.
This is the design decision I find most interesting, because it's clearly intentional. Stripe's position is that the ML model knows better than any individual operator, so there's nothing to configure. For most operators, that sounds sensible. For operators with strong opinions and visible patterns in their failure data, it doesn't.
The strategy doesn't vary by decline code
Timing is the part Smart Retries personalizes. Per Stripe's docs, "Using AI, Smart Retries chooses the best times to retry" each payment. Strategy is the part it doesn't: every retryable failure gets the same retry-it treatment, with no per-code branching into card-update emails, payday-anchored retries, or operator alerts. Take insufficient_funds near month-end - where the customer's next payday might be 5 weeks out. The retry window itself is configurable up to 2 months, but a longer window of ML-timed retries still isn't payday-aware. Nothing anchors an attempt to the dates when the account is most likely to have balance and for the charge to go through.
When Smart Retries is the right answer
This is the section my biased custom-dunning competitors usually skip, but there are real cases where Smart Retries + the basic Stripe failed-payment email is the right call, and a custom dunning tool is overkill.
Your MRR is under $10K: The dollar value of recoverable revenue at this stage is small enough that the engineering cost of integrating any dunning tool, custom or otherwise isn't a great trade. Smart Retries is free, fast to enable, and recovers most of the easily-recoverable failures. Save your attention for product-market fit.
You're pre-product-market-fit: Same reason. Recovery optimization is a problem that benefits from focused attention, and pre-PMF is when you have the least focus to spare. Turn on Smart Retries, turn on the basic failed-payment email, and revisit when you're past PMF.
Your customer base is heavily debit-card and US-domestic: Smart Retries does well on US debit cards because Stripe has a lot of training data for that population. The marginal gain from custom dunning is smallest for this segment.
You don't have a strong opinion about the decline-code strategy: If the four-category routing in the decline-codes guide doesn't feel obviously right to you yet, you might not need a tool that lets you customize it. Use Smart Retries until you have an opinion, then come back.
I'm saying this with intent. RecoverStack is not a good first purchase for a $5K MRR pre-PMF startup - Smart Retries probably is.
When custom dunning starts to make sense
On the flip side, the cases where adding a custom dunning tool on top of (or instead of) Smart Retries starts to pay for itself:
Your MRR is above $25K and you have visible failed-payment volume: At this stage, even a 10 percentage-point recovery improvement is worth a few hundred dollars a month, which covers any reasonable custom dunning tool many times over. The integration cost (self-serve setup in under 5 minutes for RecoverStack, longer for some competitors) is small relative to the recovery upside.
You have a meaningfully international customer base: Smart Retries' ML model is trained globally, but my read is that the timing it picks is most reliable for US patterns, and operators with significant European, UK, or Brazilian volume probably have the most to gain from a tool that routes those geographies to different strategies. India is the clear-cut case: per Stripe's own docs, Stripe doesn't retry India-issued cards at all, so any retry strategy there is yours to build.
You want operator-level visibility: If you want a dashboard that shows MRR at risk, current recovery rate, top decline codes, and per-customer drill-down, Smart Retries can't give you that. Stripe Sigma can give you the underlying data, but only if you're building the dashboard yourself.
You want to communicate with customers about failed payments: A multi-step dunning email sequence with branded templates, decline-code-aware copy, and one-click card-update links has consistently better recovery rates than the silent-retry-then-cancel flow. Smart Retries can't do this.
You want to keep customers post-failure: A failed payment is a moment when the customer's relationship with your product is at risk. The right email tone (acknowledging the failure, making the fix easy, and not blaming the customer) preserves trust in a way that silent retries followed by sudden access revocation doesn't. Custom dunning is partly about LTV, not just immediate recovery.
The hybrid approach (which is what I actually recommend)
Smart Retries and custom dunning aren't exclusive - the setup I'm recommending in RecoverStack's onboarding for cohort customers is to run both, with the strategies coordinated.
-
Stripe Smart Retries handles the first 24 hours of transient failures. For decline codes where retrying probably works (
processing_error,try_again_later,reenter_transaction), Stripe's ML model is good enough and free. -
RecoverStack's decline-code router takes over for everything else. For card-update codes, the customer is emailed immediately. For bank blocks, the retry varies by code.
do_not_honorgets one retry at 24h plus the card-update email sequence (three emails: immediate, day 3, day 7).card_declinedandgeneric_declineget three retries at 6h, 1d, and 7d alongside the standard dunning sequence. For fraud flags, the operator is alerted directly. -
Stripe's automatic card updater stays on always. It catches card reissues from participating banks and rewrites the card on file, which improves recovery on the codes that route to email.
The key coordination is making sure RecoverStack and Smart Retries don't double-retry. The cleanest fix, and what I'm planning for v1, is to prompt managed customers to disable Stripe's retry schedule and let RecoverStack own the retry calendar. Operators who want to keep Stripe's retries in addition will get a clear warning at connection time about the coordination implication.
What I'm still figuring out
A few things I'm genuinely uncertain about and that the cohort will teach me.
Whether the hybrid approach actually beats Smart Retries-only on transient failures: It might be that Stripe's ML model is so good on the transient codes that custom routing doesn't add anything. If cohort data shows that, I'll just hand the transient codes back to Smart Retries entirely.
The right cutoff for "Smart Retries is enough": I'm using $10K to $25K MRR as the rough zone where custom dunning starts to pay for itself. Those numbers are my own working guesses, loosely anchored on Baremetrics' figure that involuntary churn eats roughly 9% of MRR. The cohort data might push that range up or down.
Whether the operator dashboard is worth the engineering cost: Operators tell me they want visibility, but observed behavior is different from stated preference. If cohort customers don't actually log in to the dashboard much, that's a signal that the visibility lever is smaller than I think it is.
I'll publish answers on recoverstack.dev/metrics as the data comes in.
A small note on bias
Everything in this post should be read with the awareness that I'm building a product in this category. I've tried to write the "Smart Retries is the right answer" section as honestly as I would if I weren't. If you read it and think I went a bit too easy on Smart Retries, or too hard, I would like to know. Reply to any RecoverStack email or hit me at [email protected].
The flip side is also worth saying: if you're sitting at $25K-plus MRR with a visible failed-payment problem and you've been getting by on Smart Retries because nobody told you there was a better default, that's the situation I'm trying to address. The free Stripe audit will tell you what your specific failure profile looks like.
About the author. I'm Yarin Goldstein. 24, based in Israel, building RecoverStack solo as my first real business after 5 years of professional dev. RecoverStack is flat-fee dunning for bootstrapped Stripe SaaS, and the founding cohort is free through July 2026. The full story is at /about. The waitlist (40% off for life) is at /early-access.