SaaS Chargebacks and Fraud: The Indie Survival Guide
Why SaaS chargebacks happen, how Stripe fees and card-network dispute thresholds work, when it's worth fighting a dispute, and how to keep your rate low.
· Justin Boggs

Photo by Towfiqu barbhuiya on Unsplash
SaaS chargebacks are almost never about the money. A customer forgets what your product is, doesn't recognize the line on their statement, can't find the cancel button, or gets their card stolen — and their bank pulls the funds out of your Stripe balance before you've read the email. You lose the sale, you lose a non-refundable dispute fee, and your dispute rate ticks up with the card network whether you win or lose. The survival strategy for an indie SaaS isn't getting good at fighting disputes. It's making the situations that cause them rare, and refunding fast when they aren't.
TL;DR
- A dispute costs you more than a refund: the sale, a non-refundable fee, funds held for two to three months, and a permanent tick on your dispute rate.
- Card-network monitoring programs count every dispute regardless of outcome — winning doesn't help your rate, and refunds don't remove disputes already filed.
- The industry treats dispute activity above 0.75% as excessive. Visa's VAMP flags accounts at a 0.5% ratio, and the US "excessive" tier sits at 1.5%.
- Most indie SaaS disputes come from three fixable causes: a confusing statement descriptor, a hard-to-find cancel button, and a silent annual renewal.
- Card testing is the fraud you'll actually see first. It shows up as a flood of tiny declined payments, and it poisons your decline rate long after the attack stops.
What actually happens when a customer disputes a charge
A chargeback is a forced reversal initiated by the cardholder's bank, not by you and not by Stripe. Your customer calls their issuer, says "I didn't authorize this" or "I never got what I paid for," and the issuer pulls the money back through the card network. Stripe's role is to notify you and pass evidence along. It has no vote in the outcome.
The mechanics are worth knowing precisely, because they explain why the economics are so lopsided. According to Stripe's documentation on how disputes work, the moment a dispute opens the network debits Stripe for the disputed amount, Stripe debits your balance for that amount plus a dispute fee, and those funds are held for the entire dispute. You also can't issue a normal refund while the dispute is open — the only path is through the dispute process.
Then you wait. You typically have 7 to 21 days to submit evidence depending on the network. The issuer then takes 60 to 75 days to decide. The full lifecycle runs two to three months, and Stripe notes you can't reliably speed it up except by accepting the dispute outright.
The fee structure compounds it. The dispute-received fee is non-refundable for businesses outside Mexico — you pay it even if you win. If you counter, a separate dispute-countered fee applies, which Stripe does return if you win. So the best possible outcome of a fight is getting your revenue back minus one fee, three months late.
Compare that to a refund: you lose the sale, you keep the fee, the money moves immediately, and nothing gets reported to the card network. This is the same math I landed on when I wrote up my refund policy for indie SaaS, and it's the single most useful thing to internalize. A refund is a cheap problem. A dispute is an expensive one. Most of your policy design should be about converting the second into the first before it happens.
Inquiries: the pre-dispute you should never ignore
Some networks — American Express and Discover most often — open an inquiry first, which Stripe describes as a "retrieval" or "request for information." Visa and Mastercard no longer use this phase.
An inquiry is a gift. You can resolve it by providing satisfactory evidence or issuing a full refund, and you don't incur a dispute fee. Stripe is blunt about the downside of ignoring one: failing to respond signals implicit acceptance of the claim and can escalate the case into a formal, and likely unwinnable, chargeback. If an inquiry lands in your inbox, answer it that day.
Why the card networks care more than you do
Here's the part most first-time founders miss. Your dispute rate isn't just a number in your dashboard — it's a compliance metric the card networks track, and exceeding their thresholds carries fines that dwarf the disputes themselves.
Stripe distinguishes two calculations. Dispute activity is the percentage of disputes on successful payments by dispute date. Dispute rate is the same percentage by charge date. The networks' monitoring programs use dispute activity, which means a bad month of disputes lands entirely in that month even if the underlying charges are 90 days old.
Stripe's guidance on measuring disputes says the processing industry treats dispute activity above 0.75% as excessive, and that a sudden spike or steep upward trend can trigger a monitoring program before you even reach that number.

The specific programs, per Stripe's monitoring programs documentation:
| Program | Ratio threshold | Count threshold | What it costs you | | --- | --- | --- | --- | | Visa VAMP — non-compliant | 0.50% | 5 items | Visa may assess fees | | Visa VAMP — excessive (US, EU, Canada, AP, LAC) | 1.50% | 1,500 items | Fees assessed | | Mastercard ECM | 1.50–2.99% | 100–299 chargebacks | $1,000 from month 2, rising to $100,000 at 19+ months | | Mastercard HECM | 3.00%+ | 300+ chargebacks | $1,000 from month 2, rising to $200,000 at 19+ months |
Two details matter enormously for a small SaaS. First, Visa's VAMP count includes early fraud warnings, not just disputes. Visa aggregates TC15 dispute data and TC40 fraud-report data into one ratio, and Stripe notes that a transaction appearing in both reports gets counted twice.
Second, the count thresholds are your real protection. Visa's excessive tier requires 1,500 items in a month and a 1.5% ratio. If you're doing 400 payments a month, you will never hit 1,500 disputes — but the 5-item non-compliant threshold is very reachable, and the ratio matters for how Stripe itself views your account. Stripe says it reaches out proactively when it sees elevated dispute or fraud activity, and excessive activity affects your ability to process with Stripe and with any other processor.
Also worth knowing: monitoring programs don't consider outcomes. Stripe is explicit that they don't wait for dispute results, because they care more about how successfully you prevent disputes than whether you win them. Winning a dispute recovers your revenue. It does nothing for your rate.
Card testing: the fraud you'll actually meet first
Before you ever see a real fraud dispute, you'll probably get card-tested. Stripe defines card testing as fraudulent actors validating stolen card numbers by running them through someone's checkout — usually with scripts, usually at high volume, usually on the smallest amount you accept.
You are a good target precisely because you're small. Your checkout is public, your publishable key is in your frontend bundle by design, and nobody is watching your dashboard at 3am.
The symptoms are unmistakable once you know them:
- A sudden spike in failed or blocked payments on your dashboard home.
- A spike in 402 errors in your Stripe logs, mostly
generic_decline. - A cluster of tiny successful payments with nonsensical names and disposable email addresses.
The consequences outlast the attack. Stripe lists several, and the one that hurts most isn't the disputes — it's the decline rate. A large volume of declines damages your reputation with issuers and networks, which makes all your transactions look riskier and raises decline rates on legitimate payments even after the testing stops. Card testing also pollutes your revenue data, because a wave of fake signups looks like growth until you look closely.
The mitigations, in the order I'd do them:
- Use a recommended Stripe integration. Payment Element or Checkout ship with rate limiters, ML models, and CAPTCHA triggers that Stripe activates dynamically during an attack. If you rolled your own card form to save a redirect, you gave up all of that.
- Feed Stripe more signal. Stripe's card-testing models get materially better with IP address, customer email, customer name, and billing address attached to the payment, plus its advanced fraud detection script on the page.
- Put a login in front of payment. Guest checkout is the easiest surface to script against. If your product requires an account anyway, requiring session validation before checkout removes most automated traffic.
- Rate-limit the endpoints that create customers and payment methods. Limit new customers per IP per day. This is the kind of change that's a ten-line edit in a route handler and cuts an entire attack class.
- Refund suspicious payments that got through, immediately. Refunding doesn't erase an early fraud warning, but it dramatically reduces the odds of a fraud dispute on top of it.
If you're wiring this into a Next.js app, the constraint I'd hold onto is the one my own boilerplate enforces by convention: the Stripe SDK lives in exactly one file, and every other call goes through a payment-provider abstraction. When you need to add a velocity check or a CAPTCHA gate, you want one place to add it — not eleven route handlers that each talk to Stripe directly. Same principle I described in Stripe webhook hell: the integration is manageable exactly to the degree that it's centralized.
The three causes behind most indie SaaS disputes
Strip out real stolen-card fraud and most SaaS disputes trace back to three things a founder controls completely.
1. Your statement descriptor doesn't match your product name. A customer signs up for "Bloom" and sees "BGGS HLDNG LLC" on their statement six weeks later. They don't recognize it, they assume fraud, they call the bank. Stripe notes that a high volume of general or duplicate disputes often indicates exactly this — an unrecognized descriptor or a confusing billing statement. Fix: make the static portion of your descriptor the product name customers actually know, and put that same name in your receipt subject line.
2. Cancelling is harder than disputing. If a customer has to email support and wait a day to cancel, the bank is a faster path — and it's one click. Stripe's prevention guidance leads with this: offer a quick and easy way to cancel, ideally an in-app button, because it doesn't require the cardholder to wait for confirmation. I built the cancel flow into the account page for exactly this reason, and wrote up the reasoning in customer offboarding and cancel flows.
3. The renewal arrives with no warning. Annual renewals are the worst offender. A customer paid twelve months ago, forgot the product existed, and gets a large charge with no notice. Stripe's recommendation is specific: send billing reminders roughly 7 days before a yearly renewal and 2 to 3 days before a monthly one. This is a single scheduled email, and it's probably the highest-ROI dispute prevention available to a solo founder. If you already have a lifecycle email setup for your indie SaaS, the renewal reminder belongs in it today.
To that list I'd add a fourth that isn't quite a cause but changes the math: a genuinely flexible refund policy. Stripe's own prevention guidance suggests offering a full or prorated refund when someone cancels the day after being billed. Every refund you issue at that moment is a dispute that never happens.
When to fight a dispute and when to accept it
Assume you'll lose. That's not defeatism; it's the base rate. The issuer decides, the standard of evidence is theirs, and Stripe explicitly says it facilitates your case but has no influence over the outcome.
So the decision is economic. Countering costs you the dispute-countered fee (refunded if you win), plus your time assembling evidence, plus three months of uncertainty. Fight when the amount is meaningfully larger than the combined fees and you have strong, specific evidence. Accept when it isn't.
What counts as strong evidence for SaaS is narrower than for physical goods, since you have no shipping tracking. What you do have:
- Server-side login records with timestamps and IP addresses, showing the customer used the product after the charge.
- The signup record showing acceptance of your terms, with a timestamp.
- Receipt and renewal-reminder emails you sent, with delivery confirmation.
- Any support correspondence where the customer acknowledged the subscription.
Stripe's evidence best practices are clear that concise beats comprehensive: issuers review thousands of responses daily and won't comb through long files to find your argument. One page of specific, timestamped usage data beats a twenty-page export.
The practical implication for your architecture is that you need this data to exist before you need it. Logging authenticated sessions with timestamps is a five-minute decision at build time and an impossible one to retrofit after a dispute lands. If you're logging transactional email through a central helper — which the boilerplate does, so every send hits an email log table — you already have half the evidence trail.
Two categories aren't worth deliberating over at all. Some disputes are unchallengeable under network rules or local regulation, and Stripe closes them as lost immediately. And Stripe doesn't support the arbitration phase, so a lost dispute is final on the platform. A customer can withdraw a dispute after a loss, but you can't appeal one.
Frequently asked questions
What is a good chargeback rate for a SaaS business?
Below 0.5% is comfortable, and most healthy subscription businesses run well under that. Stripe notes that the industry considers dispute activity above 0.75% excessive, and Visa's VAMP flags accounts as non-compliant at a 0.5% ratio. Because a sharp upward trend can trigger scrutiny before you cross a threshold, watch the direction as closely as the number.
Does refunding a customer stop a chargeback?
Only if the refund happens first. Once a dispute is open you can't issue a normal refund — the money is already held and the only path is the dispute process. Refunding proactively, before the customer contacts their bank, is the whole point. Stripe also notes that monitoring programs don't consider refunds when counting disputes, so a refund issued after the fact doesn't remove the chargeback from your rate.
Do I need Stripe Radar for a small SaaS?
Radar's baseline protection is included with standard Stripe payments, and the recommended integrations bring CAPTCHA and card-testing suppression along with them. Custom velocity rules require a higher Radar tier. For a pre-revenue or early-revenue product, the recommended integration plus rate limits on your own endpoints covers most of what a paid tier would add.
What is an early fraud warning and should I refund it?
An early fraud warning is a report from Visa, Mastercard, or JCB flagging a payment their issuer suspects is fraudulent. Stripe reports that 80% of EFWs convert into a fraud dispute if you do nothing, unless 3D Secure liability shift applies. Its analysis suggests refunding when the charge amount is roughly at or below your dispute fee, and not bothering above about 35% higher than that fee — refunding every EFW means refunding transactions that were never going to escalate.
Can chargebacks get my Stripe account shut down?
Sustained excessive dispute activity can. Stripe says it affects your ability to process with Stripe and with other processors, and that failing to comply with a monitoring program's requirements within the specified period can result in a network refusing to process further payments to you. It's rare for a small business with normal traffic, and it's a slow-moving problem you'll be warned about — but it's the reason to take a rising rate seriously rather than treating disputes as a cost of doing business.
Should I use 3D Secure on all my payments?
Not by default. 3DS shifts fraud liability to the issuer but adds checkout friction that costs you conversions, and it doesn't protect against non-fraud disputes like "I forgot to cancel," which is what most SaaS chargebacks actually are. Reach for it selectively — higher-value plans, or after you've seen a fraud pattern — rather than blanket-enabling it.
The version of this that actually works
The uncomfortable conclusion after reading through all of Stripe's dispute documentation is that almost none of the leverage is in the dispute process. You can't appeal, you can't accelerate, you can't get the fee back, and winning doesn't repair your rate. Every meaningful lever sits upstream: a statement descriptor customers recognize, a cancel button they can find, a renewal email that arrives before the charge, a refund you issue without arguing, and a checkout that isn't trivially scriptable.
For a solo founder that's good news, because all five are afternoon-sized changes. None of them require a fraud team, a Radar tier, or a compliance consultant. They require deciding that a $29 refund is cheaper than a $29 dispute — which, once you've watched the fee come out of your balance and the money sit frozen for eleven weeks, stops feeling like a hard call.
If you're wiring Stripe into a Next.js app and want the payment layer set up this way from the start — SDK isolated to one file, webhook signature verification on every handler, cancel flow and billing emails already in place — Coding Capybaras is the free boilerplate I built for exactly that.