Fake Signups and Card Testing: A Small Defense Stack for a Tiny SaaS
If your signup form has been live for a few months, go look at your newest users table right now. Sort by created_at , scroll a bit. Most of us find the same stuff: names like xkqjvbtr , emails at domains that don't exist, five accounts from the same IP in a minute, and nobody ever logging in again. It's easy to treat that as noise. It isn't, for two reasons. It quietly wrecks your numbers, and…
If your signup form has been live for a few months, check your newest users table. You’ll see many names and emails that look suspicious. This isn’t just noise; it can significantly impact your numbers and, if a payment form is involved, lead to card testing which costs real money and damages trust with payment processors. Here’s a simple defense setup for a tiny SaaS, in order of effort. No security team is required.
First, understand what you’re dealing with: there are three main issues—junk signups, real people abusing free tiers, and card testing. Card testing is the most concerning. Someone with stolen card numbers uses your checkout or add payment method form to see which cards still work. This can result in disputes, declining real customers' cards, extra fees, and inflated revenue numbers in your data.
To identify card testing, monitor your Stripe dashboard for spikes in failed or blocked payments and many generic_decline errors from customers with odd names and emails. For junk signups, run a query to see if the number of never-logged-in accounts suddenly increases over a few days, indicating something fishy is happening.
Here’s a cheap defense stack, starting with the easiest to implement:
1. Add a CAPTCHA on signup and verify it on the server. Cloudflare Turnstile is a popular choice as it’s mostly invisible to users, but the key is checking the token on your backend. Implement a function to verify the token on each signup request. This stops most bots, though not all.
2. Rate limit the signup, login, password reset, and any card-related endpoints. Limit to about 5 signups per IP per hour. This stops most scripts and most humans alike. Stripe suggests similar limits for card testing to prevent multiple accounts from the same IP.
3. Prevent strangers from reaching the card form. If there’s a card form, require signup and email verification first. Also, restrict the number of cards one account can add—real customers usually add one or two, not nine in a short time.
4. If possible, use Stripe’s hosted payment pieces like Checkout or the Payment Element. These have built-in protections against card testing (rate limits, CAPTCHA triggers, etc.). If you’re rolling your own card form, you’re doing more work than necessary.
5. After an attack, clean up by refunding any junk payments quickly, deleting or flagging fake accounts to stop them from appearing in your numbers, and ensuring your secret key isn’t exposed in front-end code or public repositories. Also, monitor your dashboard closely for a few days to ensure the fixes worked.
Remember, even without money changing hands, fake signups can skew your product metrics. A drop in signup-to-activation rates, longer onboarding times, and inflated activation numbers can mislead you into thinking a channel is performing well when it’s actually just a bot farm. Filter out accounts that never logged in to get a clearer picture. Fake emails also bounce, which harms your sender reputation and can push important emails like password resets into spam folders.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.