A
Amey Farde
Guest
When the Score Stops Meaning What It Used To
Every ML-based risk system produces a risk score for each event/transaction. Your team sets a threshold and blocks everything above it. Simple enough to explain in a meeting, consistent enough to defend to a regulator.
Here's the problem: a score of 800 during a quiet Wednesday afternoon and a score of 800 during an active account takeover attack are not the same thing. During a normal period, a score of 800 might sit at the 95th percentile of all incoming traffic when it is genuinely anomalous, legitimately high risk. Block it!
During an attack, when a fraud ring floods your system with engineered transactions, the entire score distribution shifts upward. Now a score of 800 might sit at the 60th percentile. It's not anomalous anymore but an average for the current environment. Your system is still blocking at 800. But 800 no longer means what it used to. Your threshold hasn't changed, but the population it's measuring has meaningfully changed.This is score distribution shift : a well-documented failure mode in production ML systems where the inference distribution diverges from the training distribution, except here the divergence is adversarially induced rather than organic.
The problem is that raw scores only mean something relative to the population they come from. Most fraud systems ignore that entirely. Class rank works the same way. If you scored 85 on an exam, whether that's impressive depends entirely on how everyone else scored. An 85 when the class average is 60 is very different from an 85 when the class average is 90. The grade is identical, but the meaning is not. The fix requires maintaining a running estimate of the score distribution in real time, not a static snapshot from last quarter's calibration run.
A risk score tells you how risky a transaction looked to the model. It doesn't tell you how that transaction compares to everything else happening right now, which is the question that actually matters for a blocking decision.
Instead of asking "is this score above my threshold?" a percentile-based approach asks "where does this score rank within the current population?"
The blocking rule changes from "block everything above 800" to "block the riskiest 2% of current traffic." The intent is the same. The system is more honest about what it's actually measuring.
The engineering challenge is computing stable percentile estimates across high volume transaction streams without storing every data point. The T-Digest algorithm handles this well where it maintains a compressed sketch of the score distribution with high accuracy at the tails, which is exactly where fraud decisions concentrate. Memory footprint stays bounded regardless of traffic volume, and sketches from distributed scoring workers can be merged without centralizing raw data.
When fraud activity inflates the score distribution, a percentile based system adjusts automatically. The threshold for what counts as "top 2%" rises with the distribution. Your block rate stays consistent. Your false positive rate stays manageable. No one has to manually recalibrate at 2 AM. The distribution sketch updates continuously as new scoring events arrive, so the effective threshold adjusts on a rolling basis rather than waiting for a scheduled recalibration job.
When traffic is clean and scores are low, the threshold falls with it. The system is always measuring against the current population, not the historical one it was built on.
If your fraud system uses static score thresholds, ask your team one question: what happened to your block rate and false positive rate during your last three major fraud events?
If they spiked significantly, the model probably didn't fail, but the decisioning layer did. A quick diagnostic: plot your score distribution for a normal 24 hour window against your score distribution during the last major fraud event. If the distributions look meaningfully different but your threshold didn't move, you have confirmation the static threshold was operating on stale assumptions.
Percentile ( or live ranking) based decisioning isn't a new model, but a different way of interpreting the model you already have - one that stays calibrated to the population it's actually operating in. The score tells you something specifically: Where it sits in today's distribution tells you what to do about it.
Amey Farde is a Staff Product Manager at Intuit leading AI/ML risk platforms for fintech lending and fraud prevention. With 15 years of experience including roles at Sift, Walmart Labs, and JPMorgan Chase, he holds three US patents in ML-based fraud detection and works at the intersection of traditional ML and agentic AI to automate high stakes decisioning pipelines.
Every ML-based risk system produces a risk score for each event/transaction. Your team sets a threshold and blocks everything above it. Simple enough to explain in a meeting, consistent enough to defend to a regulator.
Here's the problem: a score of 800 during a quiet Wednesday afternoon and a score of 800 during an active account takeover attack are not the same thing. During a normal period, a score of 800 might sit at the 95th percentile of all incoming traffic when it is genuinely anomalous, legitimately high risk. Block it!
During an attack, when a fraud ring floods your system with engineered transactions, the entire score distribution shifts upward. Now a score of 800 might sit at the 60th percentile. It's not anomalous anymore but an average for the current environment. Your system is still blocking at 800. But 800 no longer means what it used to. Your threshold hasn't changed, but the population it's measuring has meaningfully changed.This is score distribution shift : a well-documented failure mode in production ML systems where the inference distribution diverges from the training distribution, except here the divergence is adversarially induced rather than organic.
Static Thresholds Are Population-Blind
The problem is that raw scores only mean something relative to the population they come from. Most fraud systems ignore that entirely. Class rank works the same way. If you scored 85 on an exam, whether that's impressive depends entirely on how everyone else scored. An 85 when the class average is 60 is very different from an 85 when the class average is 90. The grade is identical, but the meaning is not. The fix requires maintaining a running estimate of the score distribution in real time, not a static snapshot from last quarter's calibration run.
A risk score tells you how risky a transaction looked to the model. It doesn't tell you how that transaction compares to everything else happening right now, which is the question that actually matters for a blocking decision.
What Percentile Rank Does Instead
Instead of asking "is this score above my threshold?" a percentile-based approach asks "where does this score rank within the current population?"
The blocking rule changes from "block everything above 800" to "block the riskiest 2% of current traffic." The intent is the same. The system is more honest about what it's actually measuring.
The engineering challenge is computing stable percentile estimates across high volume transaction streams without storing every data point. The T-Digest algorithm handles this well where it maintains a compressed sketch of the score distribution with high accuracy at the tails, which is exactly where fraud decisions concentrate. Memory footprint stays bounded regardless of traffic volume, and sketches from distributed scoring workers can be merged without centralizing raw data.
When fraud activity inflates the score distribution, a percentile based system adjusts automatically. The threshold for what counts as "top 2%" rises with the distribution. Your block rate stays consistent. Your false positive rate stays manageable. No one has to manually recalibrate at 2 AM. The distribution sketch updates continuously as new scoring events arrive, so the effective threshold adjusts on a rolling basis rather than waiting for a scheduled recalibration job.
When traffic is clean and scores are low, the threshold falls with it. The system is always measuring against the current population, not the historical one it was built on.
The Practical Takeaway
If your fraud system uses static score thresholds, ask your team one question: what happened to your block rate and false positive rate during your last three major fraud events?
If they spiked significantly, the model probably didn't fail, but the decisioning layer did. A quick diagnostic: plot your score distribution for a normal 24 hour window against your score distribution during the last major fraud event. If the distributions look meaningfully different but your threshold didn't move, you have confirmation the static threshold was operating on stale assumptions.
Percentile ( or live ranking) based decisioning isn't a new model, but a different way of interpreting the model you already have - one that stays calibrated to the population it's actually operating in. The score tells you something specifically: Where it sits in today's distribution tells you what to do about it.
Amey Farde is a Staff Product Manager at Intuit leading AI/ML risk platforms for fintech lending and fraud prevention. With 15 years of experience including roles at Sift, Walmart Labs, and JPMorgan Chase, he holds three US patents in ML-based fraud detection and works at the intersection of traditional ML and agentic AI to automate high stakes decisioning pipelines.