Pyvorin for Fraud Detection
Batch scoring grids, feature aggregation and anomaly loops are strong measured matches; inline authorisation-path scoring is not a compiler problem.
Published May 22, 2026
Fraud systems score events — transactions, logins, sessions — against rules and models. The scoring arithmetic is small per event; the volume is enormous. That combination produces the two deployment shapes this page separates: offline grids that rescore the day's events in bulk, where throughput is the whole problem, and inline scoring on the authorisation path, where a hard millisecond budget rules. Pyvorin has measured anchors for the first shape. For the second, the honest answer is that a different runtime owns it. The boundary, with evidence, is below.
No customer appears here; the deployments described are illustrative. Every speedup names a workload from the benchmark artefact dated 13 September 2026, and arithmetic on top of those anchors is labelled an illustrative model.
The shape that accelerates: offline scoring grids
The nightly rescore is the archetype. A day's transactions — millions of events — are replayed through rule sets and feature functions to produce scores, thresholds and review queues. Per event, the work is a set of small loops: velocity counters over rolling windows, deviation scores against customer history, rule weight accumulation, simple model inference. Individually small; in aggregate, hours of CPU. This is throughput work on CPU-bound pure Python, and the suite has direct matches for its component shapes.
iot.sensor_anomaly — a rolling-window anomaly detector over a sensor stream, the closest published analogue to per-customer deviation scoring — measured 45.9x. ml.perceptron_predict, a linear-model scoring loop, measured 9.9x. statistics.correlation, the shape of co-occurrence and velocity-correlation features, measured 52.5x. crypto.simple_checksum, a per-record rolling accumulation not unlike fingerprint scoring, measured 6.8x. iot.rolling_average measured 2.0x — modest, and worth seeing, because it shows the small-input end of the range where these features live.
The range teaches the same lesson as every page in this series: 2.0x to 52.5x across shapes that differ mainly in input size and loop body. A velocity feature computed over a customer's trailing year is a large loop; the same feature over trailing five events is the iot.rolling_average row. Feature engineering for fraud — like ML feature engineering generally — is where most of the win lives, and where segmentation decides the number.
The shape that does not: the authorisation path
Inline scoring — answering the approve-or-challenge decision inside the payment authorisation flow — has a budget measured in milliseconds, a tail that matters as much as the median, and a place inside a system that cannot afford jitter. Pyvorin is a throughput tool for CPU-bound batch Python; steady-state medians do not speak to worst-case latency on a synchronous path. Where the requirement is a bounded millisecond response, the engineering answer is a runtime chosen for that contract. This page will not stretch a benchmark table to argue otherwise.
The placement that works is asynchronous: score what you can inline with the dedicated low-latency component, and let the compiled Python layer own everything with seconds or minutes of slack — the rescore grid, the review-queue ranking, the feature rebuild, the retrospective model evaluation. Fraud value is created in both places, but only one of them is a compiler problem.
An illustrative deployment
Consider a fraud operations stack. Overnight, a rescore grid replays the day's 3 million events through 40 features and a linear scorer. Assume profiling attributes 70% of grid runtime to the feature and scoring loops, 20% to event parsing and enrichment, 10% to I/O. Assume — labelled, not measured — 15x on the loop share, inside the measured range of the anchors above. The model: 0.20 + 0.10 + 0.70/15 = 0.35 of the old runtime, roughly 2.9x. On those assumptions, a four-hour grid finishes in about an hour and twenty minutes, and the review queue the analysts work from is ready when they arrive rather than after lunch.
Two assumptions in that model deserve scrutiny before reuse. The parsing share assumes events arrive as parsed records; a grid that re-parses raw payloads nightly will find parsing at 20% optimistic, since parsing measures 0.7x to 1.0x in the suite and every extra point of it subtracts from the win. The loop assumption assumes features are plain Python; features already delegated to vectorised libraries hand their time to C and leave nothing for the compiler. A profiler resolves both in an afternoon.
What a pilot looks like
A contained pilot precedes any commitment. Take the heaviest feature function from the rescore grid — the velocity or deviation loop is the usual candidate — extract it into a standalone module with a zero-argument entrypoint over a day's worth of realistic events, and run the proof sequence on it. The pilot answers the only material question: whether your loop, on your event shapes, measures anywhere near the published anchors. The honest outcomes are the familiar three. Near the anchors, and the pilot proceeds. Near 1x, and the feature is too small or too library-bound to help — restructure it or leave it. Declined, and the fallback record explains why at no cost. Deciding cheaply is the point; deciding during a production rescore is not.
One pilot detail is specific to fraud: use a representative day, including its anomalies. A grid measured over ordinary traffic tells you nothing about its behaviour when the interesting events arrive, and it is precisely on the interesting events that scoring cost concentrates, because velocity and deviation features do their longest loops there. The proof subject should include them, labelled, so the number describes the workload that matters.
Where the engineering judgement sits
The judgement specific to fraud is queue design. Because inline scoring cannot be the compiler's job, value migrates to the offline layers, and their deadlines become design parameters rather than inconveniences. An engineer who treats the rescore grid as a background afterthought gets whatever latency the grid happens to have. One who treats it as a product surface — review queues refreshed before the morning shift, thresholds re-evaluated nightly — gets direct operational value from the throughput win, and can state the SLA in minutes rather than "eventually". That reframing is worth more than any flag.
The second judgement is drift hygiene. Fraud features decay; a velocity counter measured at 15x today is measured against today's data shapes, and event volumes grow. Re-running the speed proof on the actual grid quarterly — same commands, same discipline, new data — keeps the claimed number honest as the workload drifts. The method in how to run a speed proof is built for exactly that repetition.
Proving it on your own scoring grid
python -m pyvorin support your_scoring.py
python -m pyvorin run your_scoring.py --function entry --compare --runs 5 --warmup 2
python -m pyvorin bench your_scoring.py --function entry --runs 7 --warmup 2 --json
Quote only output showing Correct: YES — non-negotiable when scores feed decisions about real customers — plus COMPILED_FULL and matched warmup and run counts. Report the median of the raw samples, keep the compile cost visible, and check fallback_count and deopt_count are zero before treating the number as native. Harness mechanics are in how to benchmark a function. Scripting the three commands into the grid's nightly job turns the proof into a standing check that costs nothing to re-run and catches drift the moment event volumes change the workload's shape. That is the entire operational case for the method: not the afternoon it saves once, but the quarters of drift it catches cheaply.
Limits, stated plainly
The anchors come from one host on one date; the distribution is the message, your measurement the verdict. Small per-event features sit at the modest end of the measured range, and the suite's micro-workloads show that below a certain size, compilation overhead makes things slower — size your features before banking numbers. Parsing and string enrichment will not accelerate. The authorisation path belongs to a latency-class runtime. Any function the compiler declines falls back to correct CPython behaviour via the path described in unsupported code and the fallback path.
Where to go next
- How to run a speed proof — the repeatable measurement method for a drifting workload.
- Benchmarks — the full 71-workload table, including every slower-than-CPython row.
- Example workload: ML feature engineering — the feature-layer analysis in detail.
- Unsupported code and the fallback path — what "declined" means in production.
Last reviewed 26 May 2026 against the benchmark artefact dated 13 September 2026 (71 workloads, 54 faster / 17 slower than CPython, suite geomean 3.16x). Anchor figures are extracted from that artefact; deployment arithmetic is a labelled illustrative model. This page contains no customer claims.