Architecture
RDA · Real-Time Detection Agent

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.

At a glance
  • 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_THRESHOLD env.
  • Audit row written for every decision before the response returns — no async write-behind.
  • Publishes to two Kafka topics: transactions.completed (all) and transactions.blocked (DECLINE only).
  • Degrades gracefully: predictions still succeed against default features when Redis is unavailable.