System Design · step by stepDesign a Fraud Detection System
Step 1 / 9

Design a Fraud Detection System — the walkthrough in full

A written version of the interactive walkthrough above — the same steps, decisions and trade-offs, laid out for reading, reference and search.

The big idea

What is fraud detection?

A stolen card is being tested on your checkout right now. You have maybe 80 milliseconds to decide: let it through and eat a chargeback, or block it — and if you block a legitimate customer, you've lost a sale and annoyed a real person. Do this millions of times an hour, against attackers who adapt the moment you catch them.

A fraud detection system scores every transaction's risk in real time and decides allow / deny / challenge within a tight latency budget. The design blends fast rules with an adaptive ML model, fed by real-time features (velocity, device, geo), and closes a feedback loop so it keeps learning as fraud evolves.

How to read this: Each step opens with a real design decision — make the call before I show you what ships. Watch the pipeline grow, and at the end kill the model and stall the feature store to see what still catches fraud. Hit Begin.

Step 1 · Why not just rules?

Static rules break

The first instinct: hardcode rules. "Block if amount > $2000 AND country ≠ home." It catches something on day one. Why does a rules-only system fail over time?

Design decision: A hand-written rule set for fraud. Why does it fail over time?

The call: They're static and gameable — fraud adapts, thresholds get evaded, and blunt limits cause false positives. — Fraudsters probe until they find the threshold and stay just under it; meanwhile rigid limits block legitimate outliers (a real customer's big foreign purchase). Rules can't capture subtle, shifting, multi-signal patterns — that needs learning from data.

Rules alone are static and gameable: attackers probe until they find a threshold and stay just under it, while blunt limits false-positive on legitimate outliers. Fraud is a moving, subtle, multi-signal target — you can't enumerate it by hand. You need a system that learns patterns from data and adapts, while keeping rules for the clear-cut and compliance cases.

Rules + learning: Rules aren't useless — they're fast, explainable, and perfect for hard blocks (blocklists, legal requirements, impossible velocity). But the subtle, evolving majority of fraud needs a model. The real system is a hybrid: rules for the obvious, ML for the rest.

Step 2 · The decision path

Score, then decide, fast

Put a decision service in the payment path. It has a hard constraint most systems don't: it must return a verdict in tens of milliseconds, synchronously, or it delays every checkout. What must it produce?

The decision service takes a transaction and returns a verdict — allow, deny, or step-up (challenge with 2FA/review) — within a strict latency budget. First pass: run fast rules (hard blocks, allowlists, compliance). Then compute a risk score and threshold it into a decision. It sits inline with the payment, so everything it does must be fast and reliable.

The latency budget rules everything: Because it's synchronous in checkout, ~50–100ms is the whole budget for features + model + rules. That constraint shapes every choice: precompute features, keep the model small/fast, cache aggressively, and degrade gracefully rather than time out a payment.

Step 3 · What the model sees

Real-time features

A single transaction — "$40, card X, IP Y" — barely tells you anything. The signal is in context: how this compares to card X's history and behavior right now. How do you get rich features within the latency budget?

Design decision: A lone transaction is weak signal. Where does the fraud signal actually come from?

The call: Just the transaction amount and country. — Amount and country alone are the weak, gameable signals rules already use. Real detection needs behavioral context — velocity and history — which a lone request doesn't contain.

Compute contextual features and serve them from a low-latency feature store. The powerful signals are behavioral: velocity (transactions per card/device/IP in the last minute/hour/day), device fingerprint and whether it's new, geo distance from the last transaction, account age, and prior chargebacks. These are precomputed and updated in near-real-time, so the scorer reads them in milliseconds instead of recomputing history per request.

Features are the product: In fraud, feature engineering beats model choice — velocity and history features carry most of the signal. The feature store serves the same features online (for scoring) and offline (for training), keeping them consistent so the model sees in production exactly what it learned on.

Step 4 · Score the subtle stuff

The ML model

Rules caught the obvious; features are ready. Now you need to turn dozens of signals into a single risk number that captures patterns no human wrote down — combinations like "new device + unusual amount + high velocity + far geo."

Run an ML model (often gradient-boosted trees for tabular fraud — fast and strong) that takes the features and outputs a fraud probability. Combine it with rules: a hard rule can veto, the model score handles the nuanced middle, and a threshold (tuned to your fraud-vs-friction tradeoff) maps the score to allow / step-up / deny. Keep the model fast (the latency budget) and monitored (fraud drifts, so a stale model quietly rots).

Model + threshold: The model outputs a probability; the business picks the thresholds — where to auto-allow, where to challenge, where to hard-deny — trading missed fraud against blocked customers. Gradient-boosted trees dominate tabular fraud, but the architecture is model-agnostic: what matters is fast scoring and a tuned decision boundary.

Step 5 · Keep features fresh

Streaming aggregations

Velocity features — "10 transactions on this card in the last 60 seconds" — are only useful if they reflect what happened seconds ago, including the transaction being scored. A nightly batch job is far too slow to catch a burst attack in progress. How do you keep them current?

Stream every event through a real-time processing layer (Kafka + Flink/streaming jobs) that maintains windowed aggregations — counts and sums per card/device/IP over sliding time windows — and writes them straight into the online feature store. So the moment a fraudster fires 50 rapid transactions, the velocity feature spikes and the very next decision sees it. Fresh features are what catch attacks while they happen.

Streaming, not batch: Fraud is a real-time adversary, so features must update in real time. Streaming aggregations turn the raw event flow into constantly-fresh velocity/behavior signals. Batch jobs still compute slow features (long-term history) offline; the fast, decisive ones are streamed.

Step 6 · Learn from the outcome

The label feedback loop

The model was trained on yesterday's fraud, but fraud evolves — a model left alone silently decays. To keep learning, you need ground truth: which transactions actually turned out fraudulent. But that truth arrives late (a chargeback can take weeks). How do you close the loop?

Collect labels from every source of truth — confirmed chargebacks, analyst verdicts from the review queue, customer reports — and feed them back to retrain the model regularly on fresh fraud patterns. Handle the label delay (chargebacks lag) by using faster proxy signals where possible and being deliberate about training windows. Continuously monitor live metrics (approval rate, fraud rate, score distribution) to catch drift before the slow labels confirm it.

The loop is the moat: A fraud system is only as good as its feedback loop. Labels → retrain → deploy → collect labels, forever. The hard part is that the best labels (chargebacks) are weeks late, so you supplement with analyst reviews and drift monitoring to react faster than the ground truth arrives.

Step 7 · The verdict & the network

Decisioning, step-up & graphs

A binary allow/deny is crude — the borderline cases deserve a middle path — and fraud is rarely a lone transaction: it's rings of linked accounts, shared devices, and reused cards. How do you decide well and see the network?

Use a three-way decision: auto-allow the clearly-good, hard-deny the clearly-bad, and step up the uncertain middle (2FA challenge or a human review queue) — turning risk into friction only where it's warranted, and generating labels. Add graph features: link accounts by shared device/card/IP/address to spot fraud rings a per-transaction view misses (one flagged account taints its cluster). Reviews and challenges feed back as high-quality labels.

Step-up beats block: The middle path is where you win: a 2FA challenge or manual review converts many would-be false positives into approved-but-verified customers. Graph/network features catch coordinated fraud that any single-transaction score can't — fraud is social, so model the connections.

Step 8 · The sharp edges

Drift, false positives & imbalance

Fraud detection has vicious edges: an adversary actively adapts (concept drift), false positives cost real revenue and trust, fraud is a tiny fraction of traffic (class imbalance), and you may have to explain a decline to a regulator.

Fight drift with frequent retraining, drift monitoring, and champion/challenger model tests. Take false positives seriously — measure the cost of blocking good customers, and prefer step-up over hard deny near the boundary. Handle class imbalance (fraud is <1%) with proper metrics (precision/recall, PR-AUC — never raw accuracy), resampling, and cost-sensitive training. Ensure explainability (reason codes per decision) for disputes and compliance, and defend the pipeline from adversarial probing and gaming.

Design for the unhappy path: Adaptive enemy → retrain + monitor + challengers. Blocking good users → step-up, measure friction cost. 1% positives → PR-AUC, not accuracy. "Why declined?" → reason codes. Unlike most ML, your data distribution fights back — the system must assume the adversary is watching.

You did it

You just designed a fraud detection system.

  • S — t
  • A
  • R — e
  • A — n
  • S — t
  • A
  • T — h
built to catch the thief in 80 milliseconds without blocking the customer — make the calls, kill the model, run the gauntlet.
Finished this one? 0 / 50 System Designs done

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.