Founder narrative
Anya Petrova7 min read3 views

The month a card-testing attack hit my signup form at $35K MRR: a fraud diary (2026)

In 2026, the endpoint you optimize for growth is the same one fraudsters optimize for abuse. A composite founder diary about the morning a card-testing bot turned a frictionless signup form at $35K MRR into a stolen-card validation service, and the 48-hour scramble to shut it down.

A solo software founder seen from behind at a minimal desk late at night, laptop screen showing a red spiking line chart, warm editorial magazine style
A solo software founder seen from behind at a minimal desk late at night, laptop screen showing a red spiking line chart, warm editorial magazine style
In this story
The attack did not want my money. It wanted to know which stolen cards still worked, and it used my signup form to find out.

I crossed $35K MRR on a Tuesday in early 2026. I know the exact day because I had just turned on a public, no-friction signup: enter an email, add a card, land in the product. No credit-card-required trial gate, no waiting room. Fewer steps, more conversions. For about nine days it was the best decision I had made all year.

On the tenth morning I woke up to 1,400 emails.

The morning the graph went vertical

They were Stripe receipts and decline notifications, stacked since roughly 3am. My phone had a payments dashboard widget on the home screen, and the little sparkline that normally crawls along at a gentle slope was a straight vertical wall.

My first, hopeful thought was that something had gone viral overnight. It took about ninety seconds of scrolling to understand it was the opposite. The "customers" had names like "asdf qwerty" and email addresses that were random strings at domains I did not recognize. Almost every charge was a tiny amount. Almost every one had failed. A few had gone through.

I was not having a good sales day. I was being used as a testing tool.

What was actually happening

This was a card-testing attack, and if you have not lived through one, it is worth understanding precisely because it does not look like the fraud you expect.

Card testing (also called carding, enumeration, or account testing) is when someone with a batch of stolen or guessed card numbers runs them against a live payment form to find out which ones are still valid. Stripe has a blunt, useful writeup of the mechanics, and the key line is that fraudsters prefer to validate cards during card setup rather than on a real purchase, because setup attempts and tiny authorizations rarely show up on the real cardholder's statement (see the Stripe card-testing guide, accessed 2026). No statement line means no complaint, which means the stolen card stays useful for longer.

My open signup form was a perfect instrument for that. It saved a card. It ran an authorization. It required nothing that a script could not fake. I had optimized every point of friction out of the exact endpoint a card tester wants most.

This is not the same thing as the month a chargeback wave froze my Stripe and I had to argue with the dispute system after the fact. Chargebacks are the bill arriving late. Card testing is the break-in happening live, in the middle of the night, at a rate no human could produce. Different problem, different fix, and I had spent my worry budget preparing for the wrong one.

The bill was not the scary part

The direct cost was real but survivable. Thousands of authorization and decline attempts, and on the custom-rate pricing I was on, some of those attempts carry a fee whether they succeed or not. I burned a few hundred dollars in fees before I got it stopped. Annoying, not fatal.

The scary part was the second-order damage, and Stripe's own documentation is honest about it. A flood of declined payments pushes up your decline rate, and a high decline rate makes issuers and card networks treat all of your traffic as riskier, including your legitimate customers. It can, if it keeps up, land you in a card-network monitoring program. In plain terms: a bot could poison my reputation with the banks badly enough that real, paying, honest customers would start getting falsely declined at checkout. My $35K MRR was not threatened by the fees. It was threatened by the possibility that my payment rails would quietly start failing for the people I actually wanted.

Around 8am I got the email I had been dreading, a fraud-activity notice from Stripe flagging unusual volume on my account. It was polite. It was also the clearest "fix this now" I have ever received.

The 48 hours that followed

I am not going to pretend I responded like a security professional. I responded like a founder who had one job that day. Here is the order I did things in, which turned out to be roughly the order Stripe recommends anyway.

First, I stopped the bleeding at the door. I put a bot check on the signup form. I used Cloudflare Turnstile, which runs invisible, non-interactive challenges to tell humans from scripts without making real users solve a puzzle (per the Turnstile documentation, accessed 2026). The important detail I almost got wrong: you have to validate the token on the server, not just render the widget, or a script simply skips the page and calls your endpoint directly.

Second, I added rate limits. Stripe's guidance is specific and I copied it almost verbatim: cap how many new customers can be created from a single IP in a day, and cap how many card-add attempts a single session can make. A real person signs up once. A script wants thousands of tries. Any limit at all breaks the economics of the attack.

Third, I stopped rewarding the pattern. I refunded the handful of charges that had gone through, because refunding a suspicious card-testing charge quickly is how you avoid it coming back as a dispute later. Then I made sure my payment retry logic would not helpfully re-run the fraudulent cards, which would have re-run the whole attack for them.

Fourth, once the fire was out, I added velocity rules in Stripe Radar to block bursts of activity that look like testing rather than buying, and I put the actual "add a card" step behind a real, logged-in session instead of an anonymous public form. The frictionless signup that had felt so clever was the whole vulnerability. I traded three seconds of user friction for not being a public card-validation service.

By the second evening the wall on my sparkline was gone. I lost no customers to this directly. What I lost was the comfortable belief that "we are too small to be a target." Card-testing bots do not check your MRR. They check whether your form answers them.

What it actually cost, honestly

A few hundred dollars in fees. Two days I had earmarked for shipping a feature. And a genuinely uncomfortable week afterward watching my legitimate decline rate, waiting to see whether the bots had done lasting reputational damage with the issuers. They had not, or not enough to notice, but I did not know that for about ten days, and that not-knowing was the real tax.

The uncomfortable lesson is that this was not bad luck. It was a design decision. I had removed friction from the one endpoint where a little friction is the entire defense. Growth optimization and fraud exposure were the same knob, turned the same direction, and I had turned it without understanding what was on the other side.

The one thing I would tell past me

Put your "add a card" step behind something a script cannot cheaply pass, before you need to, not after. A bot check plus a per-IP rate limit on signup would have taken me an afternoon to add while calm. Adding them at 8am with a fraud notice in my inbox took the same afternoon, minus the calm, plus the fees. The work is identical. Only the adrenaline is optional.

Keep reading

If you want the other side of the payments-fraud coin, the slow-bleed version rather than the overnight-flood version:

Sources

  • Stripe, "Protect against card testing" (accessed 2026): mechanics of card testing, its consequences for decline rates and monitoring programs, and recommended mitigations including CAPTCHA, rate limits, restricting form access, and Radar velocity rules. https://docs.stripe.com/disputes/prevention/card-testing
  • Cloudflare, "Turnstile" documentation (accessed 2026): non-interactive, invisible bot-detection challenges for protecting signup and login endpoints, with server-side token validation. https://developers.cloudflare.com/turnstile/
A

Written by

Anya Petrova

Anya Petrova writes first-person founder diaries for OperatorBook, reconstructed as composites from interviews with bootstrapped SaaS founders. She focuses on the months that do not make the highlight reel: the incidents, the near-misses, and the boring operational decisions that quietly decide whether a company survives.

Frequently asked questions

Is this a real founder's diary?

It is a composite. The MRR figure is self-reported and lightly rounded, and the founder is a blend of several bootstrapped SaaS operators who lived through a card-testing attack in 2026. The sequence of events, the mistakes, and the fixes are drawn from real incidents, but no single person or company is being identified. The technical facts about card testing and the defenses are sourced from Stripe and Cloudflare documentation, cited at the end.

What is a card-testing attack?

Card testing (also called carding, enumeration, or account testing) is when someone runs a batch of stolen or guessed card numbers against a live payment form to find out which cards are still valid. Attackers use scripts to try many cards quickly. Per Stripe's documentation (2026), they prefer to validate cards during card setup or with tiny authorizations, because those rarely appear on the real cardholder's statement and so rarely get reported.

How is card testing different from a chargeback wave?

A chargeback is the fraud bill arriving late: a real purchase gets disputed weeks after the fact. Card testing is the attack happening live, usually a sudden overnight flood of small or failed charges from a script. They need different defenses. Chargebacks are managed with evidence and dispute response after the fact, while card testing is stopped at the endpoint with bot checks, rate limits, and Radar velocity rules before the charges are ever created.

Does card testing hurt you even if the charges fail?

Yes. According to Stripe (2026), a flood of declined payments raises your decline rate, and a high decline rate makes card networks and issuers treat all of your traffic as riskier, which can cause legitimate customer payments to start getting falsely declined. Sustained testing can also land a business in a card-network monitoring program. There can be per-attempt fees on some pricing plans, and the fake signups pollute your growth data.

How do you stop a card-testing attack on a signup form?

Stripe's recommended mitigations (2026), roughly in the order most founders apply them: add a CAPTCHA or bot check such as Cloudflare Turnstile and validate the token server-side; add rate limits (for example, cap new customers created per IP per day and card-add attempts per session); require a logged-in or validated session before the card step instead of an anonymous public form; refund fraudulent charges quickly to avoid later disputes; and add velocity rules in Stripe Radar to block bursts that look like testing rather than buying.

Is a small SaaS really a target for card testing?

Yes. Card-testing bots do not check your revenue or your headcount. They scan for public endpoints that will save a card or attempt a payment with minimal friction. A frictionless, no-login signup form on a small product is an ideal card-validation tool for an attacker. Being small is not protection; the shape of your signup flow is what determines your exposure.

Founder narrative

The month I lost a day of customer data at $40K MRR: a data-loss diary (2026)

In 2026, the fastest way to lose your biggest customer is a backup you never tested. A composite founder diary about the night a botched production migration erased roughly 22 hours of customer data at $40K MRR, when the newer backup had been failing silently for months and the freshest clean copy was almost a day old. It covers what was lost, the email that had to go out, the agency that churned, and the restore-drill and point-in-time-recovery changes that cut the recovery point objective from about a day to five minutes.

8 min read11