Real-time fraud detection on the authorization hot path
The Real-Time Detection Agent is the only Ojuri service that sits synchronously in front of a payment. It scores every transaction and returns an ACCEPT, REVIEW, or DECLINE verdict before the caller unblocks — no external API round-trip, no per-call fee.
ONNX-served XGBoost, scored in-process
RDA is a Fastify service written in TypeScript. Each request flows through a fixed pipeline: PRE-rules, feature lookup, ONNX inference, then POST-rules. The model is a gradient-boosted XGBoost classifier compiled to ONNX and served by ONNX Runtime in the same process.
In the project’s reference benchmark — a single Apple Silicon developer workstation — that measures p99 ≈ 49µs at the model and single-digit milliseconds server-side end to end. These are reference values, not SLA targets; re-measure on your own hardware and feature shape before relying on them.
Because inference runs in-process, there is no network hop to a third-party scoring API on the checkout path — authorization latency doesn’t depend on an external vendor’s data center, and transaction payloads never leave your own infrastructure.
Deterministic thresholds and a full audit trail
Thresholds resolve in a fixed order: per-segment override, then model default, then the FRAUD_THRESHOLD environment variable. The response carries the reason codes — the top contributing features with their numeric contribution and observed value — plus model_version and threshold, so every decision is explainable and reproducible.
An immutable audit row is written for every decision before the response returns; there is no async write-behind that could lose a record. RDA then publishes to two Kafka topics — transactions.completed for all decisions and transactions.blocked for declines only — which feed the asynchronous agents.
Degrades without blocking authorization
Feature freshness comes from Redis, but RDA treats it as a cache, not a source of truth. If Redis is unavailable, predictions still succeed against default features rather than failing the transaction. Idempotency is handled with the Idempotency-Key header — set it to your transaction_id and duplicate POSTs return the cached decision instead of re-scoring.
- Fastify service in TypeScript. PRE-rules → feature lookup → ONNX inference → POST-rules.
- Serves XGBoost via ONNX Runtime at p99 ≈ 49µs at the model.
- Per-segment thresholds; resolution order is segment override → model default →
FRAUD_THRESHOLDenv. - Audit row written for every decision before the response returns — no async write-behind.
- Publishes to two Kafka topics:
transactions.completed(all) andtransactions.blocked(DECLINE only). - Degrades gracefully: predictions still succeed against default features when Redis is unavailable.