8
27 Comments

Most failed Stripe payments aren't one problem — they're two completely different ones

I've been digging into Stripe failed payments lately, and I think a lot of SaaS founders are treating them like one problem when they're actually two very different ones.

Type 1 — Timing problems
Insufficient funds, temporary holds, short-lived issues.
Retries can work here. Just need the right moment.

Type 2 — Customer-action problems
Expired cards, changed card numbers, some issuer declines.
Retrying does nothing. The customer has to update something. Another retry won't change that.

The mistake is treating both the same way: turn on retries, send a generic payment-failed email, and wait.

Type 2 failures just sit there. Unrecovered. Permanently.

Looking at failures this way changed how I think about recovery entirely — the real gap isn't retry timing, it's knowing which failures need communication at all.

Curious how others handle this: do you actually look at decline codes, or mostly rely on Stripe's built-in retries?

(I've been deep in the weeds on this building DunnAI — happy to run this breakdown on your Stripe account if you're curious.)

posted to Icon for group Saas Makers
Saas Makers
on March 30, 2026
  1. 1

    Full disclosure: I'm Avery Lin (avrlin). I've been packaging a small Stripe dunning email pack (decline-code matrix — expired/NSF/do_not_honor/SCA) with AI assistance, so take this as adjacent interest, not neutral advice.

    What I keep seeing matches your split: a lot of "failed payment" volume isn't one problem. Expired card wants a calm update-card/Portal CTA; insufficient_funds wants retry-aware timing + backup card; do_not_honor needs a different card/bank path; requires_action is SCA confirm, not guilt copy. One generic "payment failed" note burns recovery on the easy buckets.

    Curious whether you've mapped recovery by decline family yet, or still treating Smart Retries + one email as enough?

  2. 1

    Expired cards are the easy one honestly — unlike most failures, you get a heads-up. Just run a query once a month for cards expiring in the next 30 days and send a plain "hey, your card's about to expire" email. No retry logic needed, because there's nothing to retry once the card's actually gone.

    Also worth turning on Card Account Updater if it's available where you are — it quietly swaps in reissued cards behind the scenes and wipes out a good chunk of these before you ever see them.

  3. 2

    Hey — random one, but I can help you grow this with AI UGC videos on TikTok/IG. We’ve been getting solid organic traction for apps. Worth a chat if you’re open.

  4. 1

    The Type 1 / Type 2 split is the right framework and I'm surprised more dunning tools don't make it explicit. Most of them just throw retries at everything and call it done.

    I'd add a third dimension inside Type 2: timing. Even when the customer needs to take action, there's a real difference between reaching out within 24 hours vs. waiting 4 days. The customer's mental state toward your product changes fast once a payment fails. Early outreach gets treated like a helpful reminder. Late outreach gets treated like a collections notice.

    The highest-recovery sequences I've seen hit Day 0, Day 3, and Day 7 with escalating urgency and a one-click payment update link each time. Built a tool that does exactly that for Stripe if anyone wants to see what the sequence looks like in practice.

  5. 1

    The two-problem framing is exactly right and most tools conflate them. Card update requests and dunning sequences are different tools for different failure causes. RecoveryMRR focuses on the dunning side specifically: automated Day 0, Day 3, and Day 7 email sequences triggered on payment failure, connected via Stripe OAuth, $99/mo flat. Happy to share what we see on recovery rates broken down by failure type if useful to this thread.

  6. 1

    Solid framework. The Type 1 / Type 2 split is exactly the right mental model.

    One thing I'd add: most founders don't know which bucket their failures fall into because Stripe's default dashboard doesn't break it down clearly. You can see failed invoices but not the split by decline code category or by whether retries were even attempted.

    Before committing to a dunning tool — especially one with a monthly fee or revenue share — it's worth running a quick estimate on what you're actually leaking and from which bucket. I built a free calculator for this: mrr-leak-calculator [dot] vercel [dot] app

    No account connection, takes under a minute. If the number is real, there's a $19 one-time audit that maps your specific gap — Type 1 retry timing, Type 2 card-action sequences, and trial first-invoice blind spots. Single payment, no subscription, no percentage of recovered revenue.

    Useful if you want to know the scope before picking a tool.

  7. 1

    I'm integrating Stripe Connect for a two-sided platform. The failure surface is wider than subscription SaaS: you have transfer failures, payout failures, and charge failures independently, and each maps to a different actor. Have you ever done a marketplace audit?

  8. 1

    I'm still pretty new to the SaaS game, so I had no idea that kind of pricing friction was a thing. To be fair, no one has paid for my apps yet, so I haven't had the chance to find out! lol

    1. 1

      @Fluxo When you do get your first paying users, worth setting up decline code tracking early — it's much easier to build the habit before the failures pile up. Good luck with the apps!

  9. 1

    The Type 1 / Type 2 distinction is a useful mental model
    that's easy to overlook when you're first setting up
    payment recovery.

    The decline code angle is where it gets interesting.
    Codes like "do_not_honor" or "card_velocity_exceeded"
    sit in an ambiguous middle ground — sometimes retriable,
    sometimes not — and generic retry logic handles them poorly.

    One thing that made a difference in our setup was treating
    the customer communication differently based on the failure
    type. Type 2 failures get an immediate, specific prompt
    to update their card. Type 1 failures get a quieter retry
    flow first, with communication only if retries exhaust.

    The main challenge is that decline code reliability varies
    by issuer, so even a solid classification system needs
    a fallback for when the signal is ambiguous.

    1. 1

      @EspritCode The ambiguous middle ground on do_not_honor is exactly right — it's one of the hardest codes to classify reliably. We handle it with a fallback category that uses a softer communication approach rather than a hard retry or a hard "update your card" message.
      The issuer reliability variance is a real problem. Are you running this on an active SaaS currently?

  10. 1

    nice — the free-until-it-works model is smart. removes all friction.

    im selling a $19 CSV of 1,000+ marketing agency contacts across 54 countries (with SEO scores for each), and a $9 chrome extension that audits any website for SEO issues in one click. both on gumroad. the free sample strategy has been the best move so far — people download the 50-row sample and see the quality before buying the full list.

    1. 1

      @vemtraclabs The free sample strategy is smart — same logic behind DunnAI's free-until-$49-recovered model. Good luck with the CSV and extension!

  11. 1

    This is a great breakdown — especially the distinction between timing vs customer-action issues.

    I’m seeing something similar in network traffic as well. From the outside everything looks like “normal traffic”, but in reality there are completely different categories — harmless vs malicious vs automated probing — and treating them the same is the real problem.

    Curious — did you discover this mainly from data analysis, or from customer support patterns?

    1. 1

      @firegate Great parallel — the same pattern shows up everywhere: surface label vs. underlying cause. For failed payments, it was mostly data analysis — looking at decline codes and realizing the recovery logic had to be completely different for each category. Support patterns confirmed it later. What are you building in the network traffic space?

  12. 1

    A lot of recovery systems fail because they treat one surface symptom as one underlying reality.

    But “failed payment” is not a diagnosis.
    It’s a label.

    Some failures want time.
    Some failures want action.

    Misread the layer,
    and you optimize the wrong system.

    1. 1

      @HeritageLab "Failed payment is not a diagnosis, it's a label" — that's exactly the framing. The two buckets need two different systems, not one retry cadence applied to both.

  13. 1

    This framing really clicks. We use Stripe for our SaaS and I'll admit we were guilty of the "turn on Smart Retries and forget about it" approach for way too long. The wake-up call was when we actually exported our failed payment data and realized nearly half our involuntary churn was Type 2 — expired cards and hard declines where no amount of retrying would ever recover the revenue.

    The thing that surprised us most was how much of Type 2 churn was preventable with proactive communication BEFORE the card even fails. Stripe sends card_expiring webhooks, and we started emailing users 2 weeks before expiration with a direct link to update their card. That alone cut our Type 2 failures by about 30% before they even happened.

    For the Type 1 stuff, we found that retry timing matters more than retry count. A retry at 2am when banks are doing batch processing has a meaningfully higher success rate than retrying during business hours. Small detail but it compounds over time when you're running enough subscriptions.

    1. 1

      Type 2 is also where the second-order leak hides: the subscription dies from hard declines, but did the access die with it? In a lot of setups dunning exhausts, Stripe cancels the sub, and the app-side entitlement quietly stays on for weeks.

    2. 1

      Really valuable — the proactive card_expiring webhook approach is something a lot of founders skip entirely. Catching Type 2 before it happens is obviously better than recovering after.
      That 30% reduction from pre-expiry emails is significant. DunnAI focuses on post-failure recovery, but this is a good reminder that the best recovery is prevention.
      What stack are you running for the outreach side?

  14. 1

    The decline code distinction is massively underused. Most founders run retries on everything and wonder why recovery rates stay low.

    The specific codes that matter for Type 2 sorting: do_not_honor, card_velocity_exceeded, generic declines from the issuer. Those are almost always Type 2. insufficient_funds and processing_error tend to be Type 1. The issuer-level ones are sneaky because they look temporary but often aren't.

    The thing I've found helps most is the outreach timing. For Type 2 a dunning email on day 1 converts way better than day 3-4. By day 3 the customer has already mentally cancelled. Day 1 they still care.

    Also worth layering in: a direct card update link vs just asking them to log in and find billing. Removing that friction cuts 20-30% of drop-off between email opens and actual card updates.

    Good framing on the two-problem split. Most SaaS dunning docs don't make this distinction clearly.

    1. 1

      The day 1 vs day 3 timing point is underappreciated. By day 3 the mental cancellation has already happened — that's exactly right.
      The direct card update link vs "log in and find billing" friction point is also something I built into DunnAI — it generates a direct link so customers don't have to hunt.
      Curious what you're building — are you still dealing with this actively?

  15. 1

    The timing vs customer-action split is exactly right. I ran into this with a small SaaS last year and our retries looked "reasonable" on paper, but most unrecovered failures were expired cards so no retry cadence was ever going to fix them. Once we split recovery into retryable declines vs update-needed declines and sent a direct card-update link for the second bucket, recovery got a lot better.

    1. 1

      @microbuilderco That's exactly the split that matters — and most dunning setups treat both buckets the same way, which is why recovery rates stay low. The card-update link for the second bucket is the right move.
      Curious what you're building now — are you still running into this on current projects?

  16. 1

    interesting approach. have you thought about giving away a free version to build trust first? i started offering a free sample of my data product and it changed the conversion conversation completely.

    1. 1

      Thanks! Actually DunnAI is already free until it recovers $49 for you — no charge before that. The free diagnostic report is also available right after connecting Stripe. Curious what your data product is, if you don't mind sharing.

  17. 1

    building in public is underrated as a growth channel. the posts about struggles get way more engagement than the polished ones. keep sharing the real numbers.

Trending on Indie Hackers
Co-founders suck… User Avatar 82 comments I built an AI that finds the right product for your customers User Avatar 45 comments I built a tool to find people already talking about problems your product solves User Avatar 34 comments The easiest version of generation history was probably the least useful one User Avatar 32 comments What 100B+ Claude tokens actually look like inside a tiny company User Avatar 24 comments 4 months to go. Chrome extension live. Web search integrated. 4 users. $0 revenue. Still here. User Avatar 15 comments