ACH Failed Payments: Why Bank Transfer Dunning Needs a Completely Different Playbook
ACH fails less than cards but recovers worse. NACHA return codes, retry limits, and why your card dunning setup does nothing for bank transfers.
Every piece of dunning advice you've read, ours included, assumes the payment method on file is a card. Retry on the optimal day, send a pre-expiry email, show an in-app banner, pause instead of cancel. None of it is wrong, and none of it does anything for the growing share of B2B SaaS revenue that runs on ACH. Bank transfer failures don't expire, don't get replaced by a bank, and don't respond to a Smart Retry schedule tuned for card networks. They fail for entirely different reasons, on an entirely different clock, with an entirely different set of rules about what you're even allowed to do about it.
ACH fails less often. That's the trap.
The headline number makes ACH look like the easy choice. Recurly's payment data puts average credit card failure rates around 15%, against roughly 3-5% for ACH direct debit. Swap a customer from card to bank transfer and, on paper, you've cut their failure risk by two-thirds or more. A lot of finance teams stop reading right there and start pushing every mid-market and enterprise account onto ACH as a blanket policy.
What that comparison hides is recovery, not incidence. A card decline is a rejection at the point of sale — instant, and immediately actionable with a retry or a customer prompt. An ACH return is a reversal that shows up as much as 4 business days later, after Stripe has already told your system the payment succeeded. You've provisioned the account, sent the receipt, and moved on, and then the money comes back. Low failure rate, high blast radius per failure — that's the actual trade, and most billing teams size their ACH dunning setup as if the two rails were the same problem at different volumes.
Card decline vs. ACH return: different clock, different rules
| Card decline | ACH return |
|---|---|
| Fails at charge time, instantly | Charge appears to succeed, then reverses up to 4 business days later |
| One decline code, one meaning per transaction | Return coded by Nacha reason (R01-R85), each with its own retry eligibility |
| Retry policy is entirely up to you and your processor | Retry policy is set by Nacha, not negotiable — 2 attempts max, only for specific codes |
| Card expiry and reissue drive a huge share of failures | No expiry concept — accounts fail for funds, authorization, or simply not existing |
| Smart Retries picks the statistically best retry time | Retrying the wrong code is a compliance violation, not just wasted effort |
| Recoverable share is large — most declines are soft | Recoverable share is small — most common returns are non-retryable |
That last row is the one that trips up teams moving from card-first to ACH-first billing. With cards, the instinct is "when in doubt, retry" — soft declines outnumber hard ones, and Smart Retries handles the judgment call for you. With ACH, retrying the wrong return code isn't just ineffective, it's a violation of the operating rules your payment processor agreed to when they connected you to the network. The default instinct from card dunning is actively wrong here.
What the return codes actually mean
Nacha's return code system tells you not just that a payment failed, but whether you're allowed to try again. A handful of codes account for nearly everything a SaaS business will see:
- R01 — Insufficient funds. The account exists and is open, the money just isn't there yet. Retryable, up to twice, within 180 days.
- R09 — Uncollected funds. Funds are posted but not yet available for withdrawal — a hold or a pending deposit. Retryable on the same terms as R01.
- R02 — Account closed. Non-retryable. There's nothing to retry against; you need a new payment method, full stop.
- R03 — No account / unable to locate account. Non-retryable. Usually a typo or a stale account from a bank switch.
- R04 — Invalid account number. Non-retryable. The routing or account number failed format validation.
- R05 / R07 / R10 — Unauthorized debit variants. The customer says they never authorized this charge, or revoked authorization since. Non-retryable, and each one counts against the strictest of Nacha's compliance thresholds.
- R08 — Payment stopped. The receiver placed a stop-payment order. Non-retryable without a new authorization.
Of that list, exactly two codes — R01 and R09 — are retryable at all. Best practice is to wait 3-5 business days before the first retry, giving the account time to actually receive funds rather than immediately resubmitting into the same empty balance. Every other code on that list needs a different payment method or a corrected account, not a scheduled retry.
The compliance ceiling most SaaS teams don't know exists
Card businesses learn to watch their chargeback ratio because Visa and Mastercard enforce hard thresholds — we've covered those specifically in our Stripe chargebacks guide. ACH has the exact same structure, with three separate thresholds instead of one, measured over a trailing 60 days:
Source: Nacha operating rules, ACH return rate compliance thresholds
The unauthorized-returns threshold is the one worth worrying about, because it's ten times stricter than the overall rate and it's driven by customer behavior your product controls. R10 — "customer advises unauthorized" — fires when someone doesn't recognize a charge on their statement and tells their bank it wasn't approved, which is functionally identical to the "friendly fraud" dispute pattern we cover for cards. A confusing billing descriptor, a renewal nobody warned the customer about, or a buried cancellation flow all push R10 volume up the same way they push card disputes up. Cross 0.5% and your bank can require a compliance remediation plan; keep crossing it and you can lose ACH processing entirely, for every customer, not just the ones triggering returns.
Verification failures are a churn category cards don't have
Cards fail after you've charged them. A meaningful share of ACH failures happen before you ever get the chance to charge anything, during account verification. Stripe verifies a new ACH account either instantly through Plaid-style bank login, or through micro-deposits — two small test transfers the customer has to confirm within a matching window. Micro-deposit verification allows up to 10 attempts for descriptor-based matching and 3 for amount-based matching, with a 10-day timeout; miss it, and the PaymentIntent reverts to needing new payment details entirely.
That's a distinct failure mode worth tracking separately from post-charge returns: a customer who abandons ACH setup mid-verification never becomes a subscriber in the first place, and it won't show up anywhere in your churn numbers because there was no subscription to churn from. If you offer ACH as a checkout option, instant bank-login verification converts meaningfully better than micro-deposits precisely because it removes the multi-day gap where intent decays — the same reason a slow, multi-step signup flow loses signups a one-click flow wouldn't.
Building an ACH-specific recovery sequence
A dunning stack built for cards will silently do nothing for your ACH failures unless you build a parallel path. The pieces:
- Branch on payment method before you branch on retry logic. Your
invoice.payment_failedhandler needs to check whether the underlying payment method is a card or a bank account before deciding what happens next — the two need completely different logic, not a shared retry schedule. - Map the return code, not just the failure. Pull
charge.failure_codeor the ACH-specific decline detail from the webhook payload and route by code: R01/R09 go into a retry queue with a 3-5 day delay; everything else goes straight to a "we need a new payment method" email, because a retry attempt would be wasted at best and non-compliant at worst. - Set customer expectations around the multi-day lag. Since an ACH charge can look successful for up to 4 business days before reversing, don't grant full access the instant the charge initiates for new or risky accounts — a short provisional-access window that firms up after settlement avoids provisioning an account you'll have to claw back a few days later.
- Treat R05/R07/R10 as a cancellation-flow signal, not just a payment failure. A cluster of unauthorized-debit returns usually means customers are finding it easier to call their bank than to find your cancel button. That's the same root cause our cancellation flow guide addresses for card disputes, and it applies just as directly here — arguably more, given how much stricter the unauthorized-returns threshold is.
- Don't let card-focused tooling create blind spots. Features like Stripe's card account updater, which we've covered in depth, explicitly don't touch ACH — there's no card network to refresh a bank account against. If a meaningful share of your book runs on bank transfer, that entire layer of your involuntary-churn defenses is doing nothing for it, and needs its own equivalent: proactive re-verification prompts when an account has been dormant, rather than a network-side fix you can just enable.
Who should actually be on ACH
| Segment | ACH fit | Why |
|---|---|---|
| Consumer / low-ACV self-serve | Poor | Verification friction and the multi-day settlement lag hurt conversion more than the lower failure rate helps |
| SMB, card-based checkout today | Situational | Worth offering as an option, not a default — let ACH's lower fees be the pitch, not a forced migration |
| Mid-market and up, high ACV | Strong | Fewer, larger transactions mean the operational overhead of proper ACH dunning is worth it per account |
| Enterprise, invoiced billing | Strong | Often already the customer's preferred rail, with finance teams used to reconciling bank transfers |
Our involuntary churn guide notes that enterprise SaaS sees involuntary churn as low as 5-15% of total losses, partly because higher-ACV accounts skew toward ACH and bank transfer. That's real, but it's not a property of the payment rail itself — it's what happens when a lower-failure-rate rail gets paired with the operational discipline that high-ACV accounts already demand. Push ACH onto self-serve, low-touch accounts without building the return-code-aware dunning logic above, and you'll trade a higher, fast-feedback failure rate for a lower, slow-feedback one that quietly does more damage per incident.
None of this changes what happens when a customer decides on their own that they want to leave — that's a product and cancellation-flow problem, the one CancelFlow exists to solve, and it's identical regardless of what's stored as the payment method. But if you're trying to get an accurate read on how much of your churn is genuinely voluntary, run the involuntary side through our churn calculator with your card and ACH failures modeled separately. Lumping a 3% ACH return rate in with a 15% card decline rate as one blended "payment failure" number will consistently understate how well one rail is performing and how much attention the other one actually needs.
Frequently asked questions
Can you retry a failed ACH payment in Stripe?+
Yes, but only for specific return codes. Nacha permits up to two retry attempts, within 180 days of the original settlement date, and only for R01 (insufficient funds) and R09 (uncollected funds) — the ACH equivalents of a soft decline. Every other common return code, including R02 (account closed), R04 (invalid account number), R05, R07, and R10 (all unauthorized-debit variants), is non-retryable. Attempting to resubmit one of those is a Nacha rules violation, not just a wasted attempt.
Why does ACH have a lower failure rate than credit cards?+
Recurly's payment data puts average card failure rates around 15% against roughly 3-5% for ACH. The gap comes down to what each rail actually checks: a card charge can fail for a dozen reasons unrelated to the money being there — expiry, network decline, fraud block, issuer risk rules — while an ACH debit mostly just checks whether the funds exist and the account is open. Fewer failure surfaces means a lower failure rate, but the failures that do happen take days to surface instead of seconds.
How long does it take to know if an ACH payment failed?+
Up to 4 business days for Stripe to receive acknowledgment of success or failure on an ACH Direct Debit charge, compared to an instant response on a card charge. Most returns — R01 through R04 and R09 — must be filed within 2 banking days of settlement, but unauthorized-debit codes like R05, R07, and R10 carry a 60-calendar-day window, so a "successful" ACH charge can still come back as a return two months later.
What ACH return rate gets a merchant flagged by Nacha?+
Nacha enforces three separate thresholds measured over a trailing 60 days: 15% for all returns combined, 3% for administrative returns (R02, R03, R04), and 0.5% for unauthorized returns (R05, R07, R10, R29, R51). The unauthorized-return threshold is the one that catches SaaS businesses off guard, because it's ten times stricter than the overall rate and gets triggered by exactly the failure mode — a customer disputing a charge as unauthorized instead of just cancelling — that a bad cancellation flow tends to produce.
Stop losing subscribers today
One script tag. One function call. A live cancellation flow in under 10 minutes.
Start free trial →