Design a Fraud Detection System
Difficulty: Tier 3 Asked at: Tabby, Careem Pay, Stripe, banks, Amazon Time budget: 45–60 min
Fraud detection sits in the payment path and must answer “is this transaction fraudulent?” in
milliseconds, using signals about the user, device, and behavior — while fraudsters constantly adapt. It
blends real-time low-latency scoring with rules + ML models and a feature store, plus the
subtle tension of precision vs recall (block fraud without blocking real customers). A MENA fintech
favourite (Tabby, Careem Pay).
Prerequisites: Design Payment System, Batch vs Stream, Design Ad Click Aggregator
1. Requirements
Functional:
- Score each transaction/action for fraud risk in real time; approve, deny, or flag for review.
- Use signals: transaction details, user history, device fingerprint, velocity (rate of actions), geo,
network.
- Rules (hard blocks) + ML models (risk scores).
- Feed back confirmed fraud/chargebacks to improve models.
- Case management for human review of flagged items.
Non-functional:
- Low latency — scoring is inline with checkout; adds ≤ tens of ms.
- High recall (catch fraud) and high precision (don’t block legit users) — 🚨 the core tension.
- Adaptive — fraud patterns shift; the system must be retrainable/updatable quickly.
- Scale to millions of transactions/day; auditable decisions.
Out of scope: payment processing (separate), the ML training pipeline internals.
2. Estimation
- Millions of transactions/day → hundreds–thousands/sec, each needing a real-time score in < ~50 ms.
- Each score needs many features — some precomputed (user’s 30-day history), some computed live (this
session’s velocity). 🚨 Fetching/computing features fast is the latency challenge.
3. The core: real-time scoring with a feature store
🚨 The pattern: at transaction time, gather features, run them through rules + a model, produce a
risk score, decide. The trick to doing it in milliseconds is a feature store that serves precomputed
features instantly.
flowchart TB
Txn[Transaction] --> Scorer[Scoring Service]
Scorer --> FS[(Feature Store<br/>precomputed features)]
Scorer --> Live[Live features<br/>velocity this session]
Scorer --> Rules[Rules engine<br/>hard blocks]
Scorer --> Model[ML model<br/>risk score]
Scorer --> Decision{Approve /<br/>Deny / Review}
Stream[Event stream] --> FeatureCompute[Feature computation<br/>batch + streaming]
FeatureCompute --> FS
Decision --> Feedback[(Labels: confirmed fraud)]
Feedback --> Retrain[Model retraining]
Features are computed offline (batch: user’s historical stats) and in near-real-time (streaming:
velocity, recent behavior) and stored in a feature store for fast lookup. At scoring time, the service
fetches features, applies rules (instant hard blocks: blacklisted card, impossible geo velocity) and an
ML model (nuanced risk score), and decides. Confirmed-fraud labels feed retraining.
4. Deep dives
4a. Rules + ML (defense in depth)
🚨 Use both. Rules are fast, explainable, catch known patterns, and give instant hard blocks (velocity
limits, blocklists) — but they’re rigid and gameable. ML models catch subtle/novel patterns via many
features but are slower to update and less explainable. Layer them: rules for clear-cut cases and guardrails,
model for the gray area. This gives coverage + speed + adaptability.
4b. Features & the feature store
The score is only as good as its features: velocity (transactions per hour/day for this user/card/device),
historical behavior (typical amount, locations), device fingerprint, network reputation, graph features
(shared devices/cards across accounts). 🚨 Precompute expensive features offline and serve them from a
feature store so real-time scoring is a fast lookup + a model inference, not a data-gathering exercise —
exactly the pattern from the news feed ranking and ad aggregator.
4c. Velocity & streaming features
Many fraud signals are rates — “10 transactions in 2 minutes,” “same card from 3 countries in an hour.”
Compute these with streaming aggregation over the event stream (windowed counts, like the ad-click
aggregator), updating the feature store continuously so velocity features are fresh at scoring time.
4d. Precision vs recall — the central trade-off
🚨 Catching more fraud (recall) means blocking more legit users (hurting precision), and vice versa. A
too-aggressive system blocks real customers (lost revenue, angry users); too-lax lets fraud through
(losses). Tune the decision threshold, and use a three-way outcome (approve / deny / flag for human
review) so borderline cases go to review rather than a hard wrong decision. Different actions have different
risk tolerances (a $5 vs $5,000 transaction). This business-aware balancing is the senior insight.
4e. Adaptivity & feedback loop
Fraud evolves (fraudsters probe and adapt), so the system must too. Feed confirmed fraud and chargebacks
back as labels to retrain models regularly; monitor for drift (model performance degrading); allow rapid
rule updates to respond to a new attack in hours, not weeks. The feedback loop is what keeps it effective.
4f. Explainability & audit
Decisions affect customers and are regulated → record why each decision was made (which rules fired, score,
key features). Human reviewers need this; regulators may require it. Favor models with some explainability
for high-stakes denials.
5. Bottlenecks & scaling further
- Scoring latency → feature store (precomputed) + fast model inference + rules short-circuit.
- Feature freshness (velocity) → streaming aggregation into the feature store.
- Precision/recall balance → tunable thresholds + approve/deny/review three-way + per-context risk.
- Adaptivity → feedback labels + frequent retraining + fast rule updates + drift monitoring.
- Throughput → stateless scoring services scale horizontally.
6. Trade-off summary
| Decision |
Chosen |
Alternative |
Why |
| Detection |
Rules + ML (layered) |
One or the other |
Speed/explainability of rules + subtlety of ML |
| Features |
Precomputed + streaming, feature store |
Compute live |
Real-time scoring must be a fast lookup |
| Outcome |
Approve / deny / review |
Binary block/allow |
Borderline → human review, not a wrong hard call |
| Threshold |
Tuned per context/risk |
Fixed |
Balance precision vs recall by stakes |
| Model |
Retrained on feedback |
Static |
Fraud adapts; the system must too |
7. Follow-up questions
Why use both rules and machine learning instead of just one?
Because they have complementary strengths and weaknesses, and layering them gives coverage no single approach
provides. Rules are fast, deterministic, and fully explainable, and they give instant hard blocks for known-
bad patterns — a blacklisted card, an impossible geo-velocity, a hard limit — which you want as guardrails and
for clear-cut cases; but rules are rigid, must be hand-written, and are gameable once fraudsters learn them.
ML models, fed many features, catch subtle and novel patterns that no one wrote a rule for and adapt as they're
retrained; but they're slower to update, harder to explain, and can't be trusted alone for hard blocks. So you
use rules for the obvious cases and as fast safety rails, and the model for the nuanced gray area, combining
instant explainable blocks with adaptive pattern detection. This defense-in-depth also degrades gracefully:
if the model is uncertain, rules still catch blatant fraud, and if a new attack slips past the model, you can
deploy a rule in hours while the model retrains. Relying on only rules is brittle; only ML is slow to react
and opaque — together they're stronger.
How do you score a transaction in milliseconds when good features are expensive to compute?
By precomputing the expensive features ahead of time and serving them from a feature store, so scoring
becomes a fast lookup plus a model inference rather than a data-gathering exercise. Features like a user's
30-day spending history, typical locations, or graph relationships are computed offline in batch and
continuously updated, and velocity-style features (transactions in the last few minutes) are maintained by
streaming aggregation over the event stream — both written into a low-latency feature store keyed by
user/card/device. At transaction time the scoring service does a quick feature-store read to assemble the
feature vector, runs the rules (which can short-circuit to an instant block) and a fast model inference, and
returns a decision, all within the tens-of-milliseconds budget. The essential idea is to move the heavy
computation off the critical path: never compute expensive aggregates live during checkout; compute them in
advance and just look them up. It's the same precompute-features-serve-fast pattern used for feed ranking,
adapted to fraud.
Explain the precision-versus-recall trade-off and how you manage it.
Recall is the fraction of actual fraud you catch; precision is the fraction of your fraud flags that are truly
fraud. They pull against each other: making the system more aggressive (lower risk threshold to block) catches
more fraud (higher recall) but also flags more legitimate transactions (lower precision), which blocks real
customers, loses revenue, and angers users; making it more lenient does the reverse, letting fraud through.
There's no free lunch — you're choosing where on that curve to sit. You manage it by tuning the decision
threshold to the business's tolerance and, crucially, by not forcing a binary choice: a three-way outcome —
approve, deny, or flag for human review — routes borderline cases to review rather than a hard wrong decision,
recovering both a false block and a missed fraud at the cost of review effort. You also vary the threshold by
context and stakes: a small low-risk purchase can be approved more freely, while a large or high-risk one gets
stricter scrutiny, so you spend friction where the expected loss justifies it. Balancing these with business
awareness, rather than optimizing one metric, is the senior insight.
Fraud patterns change constantly. How does the system keep up?
Through a feedback loop and fast update paths. Confirmed fraud and chargebacks are captured as labels and fed
back to retrain the models regularly, so the model learns new patterns as they emerge rather than going stale
against last month's fraud. You monitor for model drift — degrading precision/recall on recent data — as a
signal to retrain or investigate. Because model retraining takes time, you also keep a fast rule-update path:
when a new attack is spotted, analysts can deploy a targeted rule within hours to stanch it immediately while
the model catches up, giving you both rapid tactical response and slower strategic adaptation. Streaming
features keep velocity signals current in real time. This combination — labeled feedback driving frequent
retraining, drift monitoring, instant rule deployment, and fresh streaming features — is what lets the system
co-evolve with adaptive fraudsters instead of being a static filter they quickly learn to bypass.
8. What junior / mid / senior answers look like
- Junior: writes a few if-statement rules (amount > X, country ≠ home) synchronously. Catches obvious
fraud; rigid, gameable, no learning, and either blocks too much or too little.
- Mid: combines rules with an ML risk score, uses features including velocity, scores in real time, flags
for review, feeds back confirmed fraud.
- Senior: layers rules + ML deliberately, serves precomputed + streaming features from a feature store for
millisecond scoring, frames and manages the precision/recall trade-off with a three-way outcome and context-
aware thresholds, builds the feedback/retraining loop with drift monitoring and fast rule updates, and
ensures decisions are explainable/auditable.
Further reading