You found the same person on their fourth trial this morning. Or you did not find anyone, and that is the problem: free-tier usage is climbing, the API bill is climbing with it, and revenue is flat. Free trial abuse looks like growth right up until you reconcile the invoice.
This post covers what that abuse costs, why the fixes founders reach for first each fail in a specific way, and what a fix that holds up looks like. The short version: stop trying to filter signups and start linking accounts.
How common it is
Founders describe it the same way every time. In one r/SaaS thread, a data-API founder watched scripted signups from a single disposable domain burn through free credits faster than paying users consumed them. In another, a founder estimated that obvious repeat signups made up 15 to 20 percent of their trials. On r/microsaas, the question was simply how anyone handles burner signups eating API credits.
Stripe sees the same shape from the network side. Between November 2025 and February 2026 its models flagged 6.2x more abusive free trials, and it reports that AI startups offering self-serve trials with direct API access see roughly 10x the attempted abuse of enterprise AI products, per Stripe's first-party fraud analysis. The same post puts suspected multi-account abuse at 7.4 percent of signups at AI companies.
A free tier that hands out compute, API calls, or generated output has a resale value, and a signup form is the cheapest way to obtain it. If a fresh account is worth $5 of inference and costs thirty seconds to create, someone will create a thousand.
What a trial abuser costs
The obvious line is the direct cost: LLM tokens, third-party API calls, storage, outbound email, whatever your free tier hands out. For an AI product that cost is real money per account, which is why Stripe's abuse numbers skew so hard toward AI companies.
The less obvious costs are worse because they compound.
Your analytics lie. Signup counts, activation rates, and trial-to-paid conversion all include the abusers, so conversion looks lower than it is and you start "fixing" onboarding that was never broken. The founder who put one in five trials down to repeats has a conversion number that is off by the same fraction.
Support absorbs it. Every abuse account that hits a limit files a ticket, and a human reads it before realizing who it is.
And the honest users pay. When the API bill forces you to cut free credits, the people you cut are the ones who were going to convert. The abuser just opens another account.
The ladder of fixes, and where each breaks
Founders try the same fixes in the same order. Each one stops the laziest version of the attack and nothing else.
Disposable-email blocklists
This is always first. You pull a list of throwaway domains, reject anything on it, and abuse drops for a week.
Then it comes back through three doors. The first is a catch-all domain. Namecheap sells first-year registrations on some extensions for 99 cents, and addy.io will attach a custom domain with catch-all aliases for a dollar a month. That domain is on no list because it is a day old and belongs to one person.
The second door is Gmail itself. Google documents that dots in a gmail.com address are ignored and that you can append a plus sign and any word to create variations that all land in one inbox. [email protected] is a new email to your uniqueness constraint and the same inbox to the abuser. Normalizing dots and plus-tags closes this door, and you should, but it is a five-minute fix and the abuser knows it.
The third door is real accounts. Gmail and Outlook accounts are free to create, and the person on their fourth trial is perfectly willing to create a fifth. Stripe's Radar rule attributes include is_disposable_email precisely because it is a cheap filter, and Stripe pairs it with counts by card, IP, and billing address because the email alone tells you almost nothing.
Blocklists catch tourists. They do not catch anyone who wants your product enough to spend a dollar.
Per-IP limits
The next move is "one trial per IP per week." This one causes more damage than it prevents.
Carrier-grade NAT means a mobile carrier puts many subscribers behind one public IPv4 address, as Wikipedia's CGNAT entry describes. An office, a university, a coworking space, and a hospital each look like one address. So does every user of the same VPN exit node. Block the address after two signups and you block the third engineer at the same company, who was the one with the budget.
Meanwhile the abuser rotates. Residential proxies and mobile hotspots hand out fresh addresses on demand, and a script can cycle them per signup.
IP is a signal. It is a weak one that should never decide anything alone, and any system that treats it as an identity will hurt teams before it hurts abusers.
Requiring a card
At some point someone says "just require a card." This advice is wrong for most of the people reading this, for two reasons.
The first is conversion. Low-friction trials are the entire mechanism of product-led growth: the user tries the product before deciding whether to trust you with a card. Put the card form first and a large share of real users leave at the form. You have traded a fraud problem for a growth problem, and the growth problem is bigger.
The second is that the card does not identify anyone. Privacy.com's free plan lets a user create up to 12 virtual cards every month, each one a distinct card number, and single-use cards close after the first charge. Stripe's free trial abuse docs name "using prepaid or virtual cards" as a common pattern. Twelve cards a month is twelve trials a month, on a card gate that cost you a chunk of your honest signups.
There is a related trap for products that validate the card with a SetupIntent. That is a $0 authorization, and $0 authorizations are also what card testers run to check stolen numbers without moving money. A card-gated trial is a free card checker, which we walk through in the card testing post. Adding the card form can bring in a second attack you did not have before.
A card is a useful signal when you collect one at conversion. As a gate at signup, it is expensive and porous.
CAPTCHAs
CAPTCHAs stop scripts. The founder losing credits to a bot from one disposable domain will see relief from a CAPTCHA, and should add one.
But the founder with one repeat in every five trials is fighting humans. A person with ten Gmail accounts solves ten CAPTCHAs. Bot protection and repeat-trial protection are different problems, and a CAPTCHA only addresses the first.
Duplicate account detection that holds: link identities
Look at the ladder again. Every rung tries to answer the same question at the signup form: is this email, IP, or card acceptable? And every rung fails because the abuser controls the one attribute you are checking.
What the abuser does not control is the correlation between attributes. Ten accounts on ten emails were created from the same laptop, or paid with the same card at conversion, or verified with the same phone, or refunded to the same PayPal wallet. Any one of those overlaps is deniable. Three of them are not.
That is identity linking. Each signup is a node with several identity keys: normalized email, device fingerprint, card fingerprint from the processor, phone number, payer wallet. When two accounts share a key, they join a cluster. The cluster is the unit of decision, and it remembers. An account that was refunded, charged back, or confirmed as a repeat trial marks the whole cluster, so the fifth signup inherits the history of the first four before it finishes loading the dashboard.
Two properties make this work where the ladder did not.
The first is that strong keys are hard to fake at scale. A device fingerprint can be rotated, but doing it per signup is work, and a card fingerprint is issued by your processor for the underlying card number, so the same physical card produces the same fingerprint across accounts no matter what email is attached. Stripe exposes card_fingerprint as a Radar attribute and counts customers per card for that reason.
The second is that IP stays out of the linking. Shared egress means two accounts on one IP are usually two colleagues, so IP should raise a score and never merge a cluster. Any linking system that fuses accounts on IP alone will merge an office into one identity and block the wrong people.
The verdict in the middle
One design decision separates a fix that survives contact with real users from one that does not.
Most repeat-trial signals are weak on their own. A new Gmail address on a device you saw last month could be a colleague on a shared machine. A datacenter IP could be a developer on a cloud workstation. A plus-tagged email could be someone organizing their inbox. Block on any one of these and your false positives will exceed your catches, and the people you block are, by construction, engaged users who came back.
So a binary allow-or-block system forces a bad choice. Either you block aggressively and lose real users, or you set the threshold high enough to be safe and the abuser walks through under it.
The fix is a third verdict. Proceed, but flag. The user gets in, the account is marked for review, and the decision to revoke happens later with more evidence: they hit the same usage pattern as the previous four accounts, or they never verified a phone, or a human looked at the cluster and recognized it. Revocation at that point is cheap because the account has done little, and the false-positive cost is near zero because the honest user never noticed anything.
Hard blocks are reserved for the cases where the cluster is already confirmed: a card fingerprint that has been charged back, a device that has burned three trials this month, a wallet attached to a refunded account.
This is the part I built Portreeve for. It links accounts across hashed identity keys, including email, device fingerprint, card fingerprint, phone and payer wallet, into clusters with memory, and returns allow, review, or block with reason codes on each signup, trial start, or trial conversion in under 100 ms. review never blocks: the flow proceeds, the event enters a review queue in the dashboard, and if you later deny it a signed webhook reaches your server so you can revoke access. Confirmed abuse reported on one account through the feedback API marks the whole linked cluster, and IP is a soft signal that never links accounts by itself.
The call at signup is one request:
import { Portreeve } from "portreeve";
const portreeve = new Portreeve(process.env.PORTREEVE_SECRET_KEY!);
const result = await portreeve.verdict({
event_type: "signup",
external_user_id: userId,
ip,
device_token, // from @portreeve/browser
email,
});
if (result.verdict === "block") { /* generic decline */ }
// "review" proceeds; the event lands in a queue you can revoke from later
The device token comes from a browser snippet, and without it the device key is missing from the graph. The device fingerprinting docs cover the setup, the handling verdicts guide covers what to do on each outcome, and the reason codes reference explains which signal fired.
Whether you use a tool or build the graph yourself, the principle is the same. Weak signals get watched, confirmed clusters get blocked, and nothing in between costs a real user anything.
What to do this week
Start by counting.
Instrument first. Before any enforcement, record the identity keys at signup and conversion: normalized email (dots and plus-tags stripped for gmail.com), device fingerprint, phone if you collect it, card fingerprint when a card is added. Then run a query for accounts that share a device or card and look at the clusters. You will learn how much of your free tier is one person, and whether the problem is ten people with a hundred accounts or a thousand bots from one script. Those need different responses, and the count tells you which one you have.
Add device signals. Email and IP are the two keys the abuser controls most easily, so a graph built only on those is thin. A device key is the cheapest strong signal to add, and it turns "five emails" into "five emails on one laptop" without touching the signup form.
Tier what a fresh account can do rather than gating the door. Keep signup frictionless and move the expensive capabilities behind a light step: phone verification, a first successful payment, or simply age. A new account that gets a small credit budget and a rate limit, with the full free tier unlocking after a week of normal use, is worth far less to a serial abuser and costs an honest user nothing. This is also the advice that surfaced in the Indie Hackers thread on repeat trial accounts: make the maintained account more valuable than a new one.
Feed decisions back. When you confirm an abuser, record it against the cluster rather than the email. When you were wrong, record that too. A graph that never learns is a blocklist with extra steps.
The people abusing your trial are patient, and they only need to beat the one check you run at the form. Stop running the check at the form.
If you would rather not build the graph, Portreeve's free tier screens 1,000 events a month with no card required. Create an account and put the first verdict on your signup route.