~/projects/fraud-detection

Fraud Detection

A risk-scoring pipeline for a client's checkout that cut fraud losses by 31.6%, built around one rule: the machine scores, a human decides.
"The hard part of fraud detection isn't catching fraud. It's catching it without catching your customers. A blocked real order is a lost customer, sometimes permanently, so the system is advisory on purpose."
31.6%reduction in fraud losses across the client's production e-commerce stack

The trap in the obvious fix

The client was losing real money to fraudulent orders and the chargebacks that followed. The tempting fix, auto-block anything that looks risky, just moves the loss: now you pay in declined legitimate orders instead of fraud. Both are losses; one of them also burns a customer relationship. So the target was never "block more", it was "lose less", and those are different objectives.

Signals, scored and routed

IP reputation and behavioral signals feed a risk score. Crucially, the weights were calibrated against the client's real chargeback outcomes, so the score reflected what actually correlated with loss, not what merely looked suspicious. The score routes; it doesn't punish.

signals · into a score

  • · IP reputation + geo/proxy heuristics
  • · behavioral signals (velocity, mismatch)
  • · chargeback history calibration

weighted by what actually correlated with loss, not what looks suspicious

machine scores · human decides

routing · never auto-punish

  • low score → passes through untouched
  • high score → flagged and routed to review
  • never an automatic block or refund

A missed fraud costs a chargeback. A false decline costs a real customer, and often for good. Because those failures aren't symmetric, the automated half stops at scoring, and the irreversible call stays with a person.

Why chargebacks were the ground truth

"Looks like fraud" is a hunch; a chargeback is a confirmed loss with a dollar amount attached. Anchoring the scoring on chargeback history meant the model was tuned against outcomes that had actually cost the client, which is what kept it from over-fitting to superficial signals like an unfamiliar country or a mismatched time zone that, on their own, flag plenty of perfectly real customers.

what I deliberately didn't automate

No automatic blocks. No automatic refunds. The system's job ends at "this order is worth a human's attention, and here's why." An irreversible action taken on a false positive is worse than the fraud it was trying to stop, so the automation stops short of the irreversible step. This is the same instinct as the RBAC gateway that logs but never bans: let the machine narrow the decision, keep the costly call human.

Client work, so the code and the client stay private. The approach is the artifact.

← all projects