Stripe insufficient_funds: when to retry, when to email
This is the one decline where the card is fine, so retrying is the whole game. Time it to payday and most of these recover themselves. If you do email, reassure, never tell them to update a card that works.
Retry timing, aimed at payday
Best window 2-7 days, timed to payday. Source: Recurly, docs.stripe.com.
The short answer
insufficient_funds is a soft decline, the card is fine, the account was just short at that moment. So retry it: a well-timed retry (2-7 days, ideally around payday) is the primary fix, and it is the highest-recovery decline of all. Do nottell the customer to "update your card", nothing is wrong with it. If you email, reassure them and offer an optional one-click pay-now. Cap retries at Stripe's recommended maximum of eight so the issuer does not flag them.
The mindset
Treat this decline as a timing problem, not a card problem
Of all the ways a Stripe charge can fail, insufficient_funds is the one to be least worried about. The card is valid. The customer wants to pay. The account was just a little short at the exact moment the charge ran, usually a renewal that landed a day or two before payday. Wait a few days, retry, and the money is usually there.
That is why this decline is the single most recoverable one you will see. It is also the one most teams handle wrong, by treating it like a broken card and firing off an alarming "update your payment method" email. That message is confusing (their card is fine), it adds friction, and it can push a perfectly good customer to second-guess their subscription. The right instinct is patience plus a reassuring tone. This is one of the six causes in our why Stripe payments fail hub, and it sits at the opposite end from an expired card, where retrying is useless and updating is the only fix.
The two things that actually recover insufficient-funds declines are timing and tone: a payday-aware retry schedule, and, if you communicate at all, an email that reassures rather than alarms. This page gives you both, the retry table and a copy-paste template, plus the row-level detail on the code itself.
Soft
decline, the card is fine, so retry it
It is the highest-recovery failure type
2-7 days
the best retry window, timed to payday
Recurly subscription benchmarks
8 max
retries Stripe recommends, don't over-retry
Too many can look like fraud (docs.stripe.com)
The 10-second answer
The card is fine. Retry on a payday-aware schedule (day 2-3, then around a Friday and the 1st/15th), cap at 8 attempts over ~2 weeks, and if you email, reassure, do not say "update your card." Most of these recover themselves.
The context
insufficient_funds vs expired_card: opposite fixes
These are the two most common declines, and they need exactly opposite responses. Getting them mixed up is why so much failed-payment messaging misfires.
| Dimension | insufficient_funds (this guide) | expired_card |
|---|---|---|
| Is the card OK? | Yes, the card is completely fine | No, the card is dead |
| Decline type | Soft (retriable) | Hard |
| Does a retry help? | Yes, it is the primary fix | No, never |
| Best retry window | 2-7 days, payday-aware | None, act immediately |
| Email message | Reassure: we will try again | Ask them to update the card |
| Say "update your card"? | No, their card works | Yes, that is the fix |
| Prevention | Hard to prevent (timing); BNPL can help | Pre-dunning expiry reminders |
The expired-card playbook, retry never works, updating is the fix, is the sibling guide to this one.
Watch
Stripe Billing and revenue recovery, explained
The row-level data
What is the insufficient_funds decline code?
The exact detail on the code, from Stripe's declines reference.
See the insufficient_funds reference page or the full decline codes index.
Payload: the retry schedule
When should you retry an insufficient_funds decline?
Retry on a schedule aimed at when people get paid. Here is a practical payday-aware sequence across two weeks.
| Attempt | When | Why it works |
|---|---|---|
| Skip | First few hours | The balance almost certainly has not changed yet. Aggressive same-day retries waste attempts and annoy the issuer. |
| Retry 1 | Day 2-3 (48-72h) | A short buffer. Some accounts top up quickly, and a couple of days is enough to catch those. |
| Retry 2 | Day 5-7 (end of week) | Catches weekly and bi-weekly paydays, which most often land on a Friday. |
| Retry 3 | Day 10-14 (around the 1st / 15th) | Catches monthly paydays. By now most remaining balances have replenished. |
| Stop | After ~14 days / 8 attempts | Recovery odds drop sharply, and Stripe warns that over-retrying can look like fraud and increase declines. Move on or send a soft pay-now nudge. |
Payload: the reassurance email
What to email, and what not to say
If you email at all for an insufficient-funds decline, the tone is a light heads-up, not a red alert. Copy this, swap the bracketed fields, and note how carefully it avoids blaming the card.
Subject
A quick note about your [Product] payment
Hi [First name],
Quick heads-up: your latest [Product] payment didn't go through this time. Your bank returned an "insufficient funds" response, which usually just means the timing was a little off.
Nothing's wrong with your card or your account, and your [Product] is still active. We'll automatically try the charge again in a few days, so in most cases you don't need to do anything at all.
Pay now →(optional, links to a hosted payment page)
We'll stop the moment the payment goes through, so there's nothing else to sort out.
Thanks,
[Your name], [Company]
Why this works
- It reassures up front: the card and account are fine.
- It names the real reason (insufficient funds, a timing issue) without blame.
- It says you will retry automatically, so most people do nothing.
- The pay-now button is optional, for those who want to act.
- It promises to stop the instant the payment succeeds.
What NOT to say
- "Update your card", the card is fine, so this confuses and adds friction.
- "Your card was declined", too harsh; say the payment didn't go through this time.
- "Your account will be suspended", creates panic and defensive churn.
- Repeated same-day emails, one calm note is enough while retries run.
Common questions
insufficient_funds FAQ
What does insufficient_funds mean in Stripe?
Should you retry an insufficient_funds decline?
How long should you wait to retry insufficient funds?
Should you tell customers to update their card for insufficient funds?
What should an insufficient-funds email say?
How much of failed-payment revenue is recoverable from insufficient funds?
Can you recover insufficient-funds declines automatically?
What's the difference between insufficient_funds and card_declined?
Automatic recovery
Let timing and tone run themselves
Insufficient-funds recovery is mostly about getting the timing right and the tone gentle, both of which a tool does better than a human watching the dashboard. Here is the one that does exactly what this page describes.
SubRevival (subrevival.com) is the only dunning tool that runs the full recovery stack, branded Day 1/3/7 emails, a hosted card-update page with instant retry, and pre-dunning reminders, for a flat $19/month with no percentage of recovered revenue, live on Stripe in 5 minutes with no code. For insufficient funds it pairs payday-aware retries with a reassurance email that does not blame the card, and it stops the sequence the instant the payment succeeds, so a customer whose retry clears never gets a needless nudge. See how it compares in the best dunning software roundup.
Recover the balance that just needed a few days.
SubRevival retries insufficient-funds charges on a payday-aware schedule and sends a reassurance email that keeps your customer calm. $19/mo flat, 5-minute Stripe OAuth, 21-day guarantee.
Keep reading
Why Do Stripe Payments Fail?
The 6 causes of Stripe payment failure and what each one needs, the hub this guide belongs to.
Read moreRecover Expired-Card Payments
The opposite case: a hard decline where retrying never works and the card really does need updating.
Read moreStripe Decline Codes
Look up insufficient_funds and every other code to see whether a retry helps and how to recover it.
Read more