How to add fraud checks without losing real customers
Every fraud check has two error rates, and only one of them is visible. You will notice the fraudsters who get through, because they cost you money in ways that show up on a dashboard. You will never notice the real customers you turned away, because they simply leave. That asymmetry is why fraud systems drift toward being too strict over time.
- 1
Never let a check fail closed
If your fraud provider is slow, down, or you have hit a quota, the signup must still work. A fraud check that takes signups offline during an outage has cost you more than the fraud it was bought to stop — and unlike fraud, it hits every legitimate user at once rather than a few bad ones.
let trust = { verdict: "allow", scored: false }; try { trust = await lc.scoreUser({ ip, email }); } catch (err) { log.warn("fraud check unavailable", err); // proceed anyway } - 2
Use the middle option
Allow and block is a false choice, and it forces every uncertain case into one of two wrong answers. A third path — verify — resolves almost everything: a one-time code costs a real person a few seconds and costs an automated attack the whole run.
- 3
Log what you rejected, then read it
Store the score and the reasons for every signup you challenged or refused, then actually look through them weekly. This is the only way false positives become visible. If you find a category of real customer in there — a country, an email provider, a VPN — that is a rule to loosen, not a coincidence.
- 4
Start in observe-only mode
Run the checks and record the verdicts without acting on them for a week or two. You will see what proportion of your normal, healthy traffic would have been challenged before you inconvenience anybody. If that number surprises you, better to learn it from a log than from your support inbox.
What this gets wrong
Every check here has a cost in real customers. These are the ones that actually bite — several because we shipped them ourselves.
- Turning the strictness up after an incident and never turning it back down. Ratchets only go one way, and nobody is measuring the cost.
- Never distinguishing "low risk" from "we could not check". They are completely different, and collapsing them means an outage looks like a clean bill of health.
- Judging accuracy by fraud caught alone. A system that blocks everyone catches all fraud. The number that matters is how many real customers it cost.
- Trusting a vendor who never publishes their mistakes. Every one of these systems has false positives, including ours — a provider who will not talk about theirs has not stopped having them.
Try it before you integrate
Paste any IP, email, phone or domain into the playground — no signup. Or get a free API key for 1,000 lookups a month, no card.