Built in Rust  ·  gRPC-native  ·  Sub-millisecond

The graph engine built for
real-time fraud decisions

JetGraph is a purpose-built in-memory graph engine that gives you velocity counts, relationship novelty signals, and fraud contagion scores in under a millisecond — exactly when a transaction is happening.

0.05ms
Velocity lookup (O(1))
35k
Events per second (streaming)
0.05ms
Fraud context read
<0.5ms
Time-window aggregation

Not another general-purpose
graph database

Every design decision in JetGraph was made specifically for one problem: scoring a transaction in real-time, correctly, with no compromises on latency.

O(1) Velocity at Query Time

Velocity windows are pre-computed as ring counters — 1min, 5min, 1hr, 24hr. No aggregation happens at query time. You get the exact transaction count for any window in a single DashMap lookup.

0.05ms · GetVelocityCount
🦠

Automatic Fraud Contagion

Flag one node as fraudulent and every directly connected entity — cards, IPs, merchants, devices — instantly reflects contamination. No batch jobs, no manual propagation. One call, graph-wide awareness.

Propagates in microseconds
🔬

Novelty Detection Built-In

Know instantly if a card has ever transacted with a specific merchant, IP, or bank — before the transaction is recorded. Structural relationship tracking gives you "first-time" signals that rules engines can't.

O(1) · CompactEdge store
🦀

Rust Performance, Zero GC Pauses

Written entirely in Rust. No garbage collector means no unpredictable latency spikes under load. Memory layout is optimized: strings are dictionary-encoded, booleans are bit-packed, integers are compact.

Deterministic sub-ms latency
📡

High-Frequency Streaming Ingestion

BatchMutate is a bidirectional gRPC stream that eliminates per-event TCP round-trip overhead. Push 35,000+ events per second from a single stream with full backpressure and acknowledgement.

~35k ops/sec · single stream
📊

HyperLogLog Cardinality at Scale

Count unique neighbors — "how many distinct cards used this IP?" — with HyperLogLog in O(1). No full traversal, no counting. Works even when a node has millions of connections.

0.06ms · GetNeighborCount

Query first. Score. Then insert.

JetGraph is designed around a precise three-phase pattern that gives you accurate, consistent signals every time — without reading your own writes.

Phase 01
🔍

Query Historical State

Before the transaction is recorded, query the graph for every signal you need. The graph reflects only past behavior — giving you a clean baseline.

GetVelocityCount(card, 1hr)
GetNeighbors(card → merchant)
GetFraudContext(card)
GetNeighborCount(ip)
QueryEdgeWindow(sum amount)
Phase 02
🎯

Score & Decide

Combine graph signals into a composite risk score. Apply your own weights and business logic. JetGraph gives you the building blocks — you control the model.

risk < 0.4 → Approve
risk 0.4–0.7 → Challenge (3DS)
risk > 0.7 → Decline
Phase 03
📝

Insert & Propagate

Record the transaction — always, even declined ones. Card-testing attacks only show up if you log every attempt. Flag declined nodes and contamination propagates automatically.

UpsertEdge(card_transaction)
CreateEdge(card_ip, if new)
FlagNode(card, if declined)

Flag one node.
The graph learns.

When a card is confirmed fraudulent, JetGraph instantly propagates contamination to every directly connected entity. Merchants, IPs, banks — they all become aware without any additional queries.

🎯

Direct fraud score

The node you flag carries a direct fraud score and reason — queryable in a single O(1) DashMap read.

🌊

Neighbor contamination

All connected nodes get their max_neighbor_fraud_score and fraudulent_neighbor_count updated automatically.

↩️

Clean false-positive recovery

Unflag a node and contamination on all neighbors is decremented atomically. No stale data.

Live Contagion Propagation
🌐 IP · 1.2.3.4
💳 Card · FLAGGED
🏦 Bank · Citibank
↕ card_ip
↕ card_tx
↕ card_bank
🌐 IP · shared
🏪 Merchant
📱 Device
Flagged (direct_fraud_score)
Contaminated (neighbor_score++)

Numbers that matter at decision time

Measured on a single machine. Every number reflects what your scoring path actually calls.

Query Latency — Single Machine
GetFraudContextTwo DashMap lookups, O(1) 0.05 ms
GetVelocityCountPre-computed ring, O(1) 0.05 ms
GetNeighborCount (HLL)HyperLogLog estimate, O(1) 0.06 ms
GetNeighbors (1 neighbor)Hot-layer + cold CSR merge 0.5 ms
GetNeighbors (100 neighbors)Scales with degree 0.9 ms
QueryEdgeWindow (1hr, ~12 edges)Binary search + property lookup < 0.5 ms

Ingestion Throughput

BatchMutate streaming — bidirectional gRPC eliminates per-event round-trip overhead.

BatchMutate (streaming) ~35,000 ops/sec
CreateEdge (unary gRPC) ~10,000 ops/sec
Pre-computed Velocity Windows
1 minute window O(1) lookup
5 minute window O(1) lookup
1 hour window O(1) lookup
24 hour window O(1) lookup

Designed for
in-process speed

JetGraph stores everything in memory with a layout optimized for read-heavy fraud scoring. No serialization on the critical path. No disk I/O during queries.

🗄️

Compact edge store

Edges are stored one record per unique src–dst pair with time-to-live support. No write amplification, no compaction pauses.

💾

Memory-efficient encoding

Strings are dictionary-encoded, booleans are bit-packed, timestamps stored as 64-bit epoch microseconds. The graph fits more data in less RAM.

📸

Snapshot persistence

The engine snapshots its full state to disk on a configurable interval. Recovery loads the latest snapshot — no WAL replay, fast restart.

🐳

Docker-native deployment

Single binary. Drop in a Docker Compose file. Mount a data volume for snapshots. No cluster to manage for most workloads.

API Layer
gRPC / HTTP2 — port 50051 SchemaService · GraphService · FeatureService
REST / HTTP1.1 — port 8080 Admin · tooling · quick testing
↓ async Tokio runtime
Engine Layer
Graph Engine (Rust) Concurrent writes · DashMap sharding
Feature Engine Velocity rings · HLL · Fraud context · Timelines
↓ lock-free reads / RwLock writes
Storage Layer
Compact Neighbor Store One record per src–dst pair · TTL eviction
Node Histograms · Activity Bitmaps HyperLogLog cardinality · per-node timelines
↓ background snapshot task
Persistence Layer
Snapshot — v4 binary format Configurable interval · fast recovery · no WAL replay

Where JetGraph fits

Any domain where relationships, history, and propagation matter — and where you need answers before the user finishes checking out.

Card Payments

Real-Time Transaction Scoring

Score every card transaction against full historical context: velocity, novelty, spend patterns, and neighbor fraud contamination — all in one sub-millisecond decision path. Plug into any authorization flow.

velocity_1min is_new_merchant spend_1hr neighbor_fraud_score
Account Takeover

Login & Session Anomaly Detection

Track which IPs, devices, and locations an account has historically used. Flag anomalous logins the instant a new device or geography appears, even before a transaction occurs.

is_new_ip is_new_device login_velocity ip_unique_accounts
Merchant Risk

Merchant Fraud Network Detection

Map relationships between merchants, acquiring banks, and card cohorts. A merchant receiving an unusual proportion of flagged cards surfaces automatically through the contagion layer.

merchant_fraud_score flagged_card_ratio chargeback_velocity
Identity Fraud

Synthetic Identity & Ring Detection

Detect synthetic identities by tracing shared attributes — same phone, address, device fingerprint, or IP — across multiple accounts. HyperLogLog cardinality queries make this affordable even at millions of nodes.

shared_ip_count shared_device_count address_reuse

From zero to first
fraud signal in minutes

The fraud-graph-client Rust crate gives you a typed, ergonomic API over gRPC. No proto files to copy, no build.rs to write.

1

Add the client crate

Add fraud-graph-client to your Cargo.toml and connect.

2

Register your schema

Declare node types, edge types, velocity windows, and property schemas once at startup.

3

Query → Score → Insert

Follow the three-phase pattern on every transaction. Collect signals, make a decision, record the result.

🦀

Rust Client

Native crate with typed API

🐍

Python Client

Protobuf gRPC bindings

🌐

REST API

HTTP/1.1 for tooling & admin

score_transaction.rs
// Phase 1: query historical state let card_id = lookup_node(&graph, "card", &tx.card_pan).await; // Velocity — O(1) pre-computed rings let tx_count_1hr = features .get_velocity_count(VelocityQuery { node: card_id, edge_type: "card_transaction".into(), window_secs: 3600, }).await?.count; // Novelty — is this a new merchant relationship? let is_new_merchant = !edge_exists( &graph, card_id, merchant_id, "card_merchant" ).await; // Fraud contagion — O(1) DashMap read let ctx = features .get_fraud_context(FraudContextQuery { node: card_id, }).await?; // Phase 2: score let mut risk: f32 = 0.0; if is_new_merchant { risk += 0.15; } if tx_count_1hr > 30 { risk += 0.25; } risk += 0.5 * ctx.max_neighbor_fraud_score; let decision = match risk { r if r > 0.7 => Decline, r if r > 0.4 => Challenge, _ => Approve, }; // Phase 3: insert — always, even if declined graph.create_edge(CreateEdgeRequest { edge_type_name: "card_transaction".into(), src: card_id, dst: merchant_id, properties: vec![prop("decision", decision)], }).await?; if decision == Decline { // Contamination propagates automatically features.flag_node(FlagRequest { node: card_id, fraud_score: 0.85, reason: "auto_decline".into(), }).await?; }

Ready to cut fraud decision latency?

Get JetGraph running in minutes with Docker. Full documentation and client libraries included.

$
docker compose up jetgraph