Built in Rust  ·  openCypher Subset  ·  Bolt  ·  Streaming Ingest

Real-time graph intelligence for
fraud and risk decisions

Purpose-built in-memory graph engine for the decision path — sub-millisecond velocity, novelty, and risk propagation, with Cypher, Bolt, and streaming ingest so you can score every event against full relationship context.

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

Not another general-purpose
graph database

Every design decision optimizes for one thing: answering relationship and velocity questions on the fraud and risk decision path — with deterministic sub-millisecond latency on a single node. openCypher subset, Bolt for compatible drivers, and streaming ingestion built in.

O(1) Velocity at Query Time

Velocity windows are pre-computed as ring counters — 1min, 5min, 1hr, 24hr. No aggregation at query time. Get exact event counts for any entity in any window with a single DashMap lookup.

0.05ms · GetVelocityCount
🌊

Automatic Risk Propagation

Flag one node as high-risk and every directly connected entity instantly reflects its exposure score. No batch jobs, no manual propagation — one call and the entire neighborhood is updated in microseconds.

Propagates in microseconds
🔬

Novelty Detection Built-In

Know instantly if two entities have ever been connected before — before the event is recorded. Structural relationship tracking gives you "first-time" signals for cards, devices, merchants, IPs, and accounts.

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
📡

Streaming Data Ingestion

High-throughput streaming pipeline built on bidirectional gRPC — eliminating per-event TCP round-trip overhead. Push 35,000+ events per second from a single stream with full backpressure, acknowledgement, and zero data loss.

~35k ops/sec · single stream
📊

HyperLogLog Cardinality at Scale

Count unique neighbors — "how many distinct users bought this product?", "how many hosts touched this IP?" — with HyperLogLog in O(1). No full traversal. Works at millions of connections.

0.06ms · GetNeighborCount
🔤

openCypher Subset

Write graph queries in a focused openCypher subset — MATCH, CREATE, and CALL procedures for the decision path. Not full Neo4j Cypher. Run via POST /cypher or the visual Cypher Editor in the admin UI.

MATCH · CREATE · CALL procedures
🔌

Bolt for Compatible Drivers

JetGraph speaks Bolt on port 7687 so Neo4j-compatible drivers can connect. Use them for the supported openCypher subset — not as a drop-in replacement for every Neo4j query or procedure.

Port 7687 · supported Cypher subset

Why not Neo4j for this path?

Neo4j is an excellent general-purpose graph database. JetGraph is built for a different job: sub-millisecond fraud and risk signals on every event.

Decision latency, not traversal flexibility

Velocity rings, novelty checks, and neighbor risk are pre-computed for O(1) reads. You get deterministic sub-ms answers on a single node — not multi-hop Cypher traversals under load.

📡

Ingest + score on the hot path

Streaming BatchMutate (~35k events/sec) and Feature APIs are designed for authorize-time scoring. General-purpose graph DBs optimize for richer queries and analytic workloads, not this write-then-score loop.

🌊

Risk primitives built in

Flag a node and exposure propagates to neighbors automatically. Novelty and velocity are first-class — not something you rebuild with custom procedures, batch jobs, or an external feature store.

Query first. Enrich. 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 event is recorded, query the graph for every signal you need. The graph reflects only committed history — giving you a clean, consistent baseline.

GetVelocityCount(entity, 1hr)
GetNeighbors(node → related)
GetNodeContext(entity)
GetNeighborCount(node)
QueryEdgeWindow(aggregate)
Phase 02
🎯

Enrich & Decide

Combine graph signals into a composite score. Apply your own weights and business logic. JetGraph supplies the primitives — your application controls the model and the outcome.

score < 0.4 → Allow / Recommend
score 0.4–0.7 → Review / Throttle
score > 0.7 → Block / Escalate
Phase 03
📝

Insert & Propagate

Record every event — including rejected or low-confidence ones. Flag nodes that breach your thresholds and propagation updates all connected entities automatically.

UpsertEdge(entity_event)
CreateEdge(new_relationship)
FlagNode(entity, if threshold)

Flag one node.
The graph learns.

When any node is flagged as high-risk or compromised, JetGraph instantly propagates its exposure score to every directly connected entity — users, IPs, products, devices — without any additional queries.

🎯

Direct risk score

The node you flag carries a direct risk score and reason — queryable in a single O(1) DashMap read from any part of your application.

🌊

Neighbor exposure

All connected nodes get their max_neighbor_risk_score and flagged_neighbor_count updated automatically.

↩️

Clean false-positive recovery

Unflag a node and exposure on all neighbors is decremented atomically. No stale scores, no manual cleanup.

Live Risk Propagation
🌐 IP · 1.2.3.4
👤 Entity · FLAGGED
🏢 Org · Linked
↕ entity_ip
↕ entity_event
↕ entity_org
🌐 IP · shared
📦 Resource
📱 Device
Flagged (direct_risk_score)
Exposed (neighbor_score++)

Numbers that matter at decision time

Measured on a single node. Every number reflects real API calls on the critical decision path — not a distributed cluster benchmark.

Query Latency — Single Machine
GetNodeContextTwo 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
single-node decision latency

JetGraph stores everything in memory on one machine — optimized for read-heavy, latency-sensitive fraud and risk workloads. 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 on a single node. Drop in a Docker Compose file. Mount a data volume for snapshots. Optional warm standby for failover — not a distributed query cluster.

API Layer
gRPC / HTTP2 — port 50051 SchemaService · GraphService · FeatureService · BatchMutate stream
REST + Cypher — port 8080 POST /cypher · Admin · tooling · quick testing
Bolt Protocol — port 7687 Compatible drivers · openCypher subset · streaming results
↓ async Tokio runtime
Engine Layer
Graph Engine (Rust) Concurrent writes · DashMap sharding
Feature Engine Velocity rings · HLL · Node 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

Built for fraud and risk —
useful wherever relationships and time matter

Core primitives — velocity, novelty, propagation, cardinality — are optimized for authorize-time risk scoring, and transfer to adjacent real-time decision workloads.

Fraud & Risk

Real-Time Risk Scoring

Score every event against full historical context: velocity, novelty, spend patterns, and neighbor risk exposure — all in one sub-millisecond decision path. Plug into any authorization or review flow.

velocity_1min is_new_relationship neighbor_risk_score spend_1hr
Recommendations

Personalization & Collaborative Filtering

Model user–item interactions as a live graph. Query which items a user's closest neighbors have engaged with, detect novelty ("never seen this product before"), and serve personalized signals in under a millisecond.

item_affinity_score is_new_item neighbor_purchases interaction_velocity
Network Security

Threat Detection & Lateral Movement

Map relationships between hosts, IPs, users, and services. Flag a compromised endpoint and propagation immediately exposes all connected assets. Detect lateral movement patterns before they escalate.

is_new_connection host_risk_score access_velocity neighbor_exposure
Identity & Access

Anomalous Login & Session Detection

Track the full history of which IPs, devices, and locations each identity has used. Surface anomalous sessions the instant a new device or geography appears, before any downstream action is taken.

is_new_ip is_new_device login_velocity ip_unique_accounts
Supply Chain

Entity Relationship & Anomaly Analytics

Model suppliers, components, logistics nodes, and certifications as a live graph. Detect unusual relationship patterns, compute supplier exposure when a node goes high-risk, and track velocity of supply events in any window.

supplier_risk_score shipment_velocity is_new_supplier neighbor_disruption
Knowledge Graph

Entity Resolution & Graph Enrichment

Build a live knowledge graph of entities and their relationships across heterogeneous data sources. Use HyperLogLog cardinality to detect entity clusters, and Cypher queries to traverse and enrich in real time.

entity_overlap shared_attribute_count cluster_size co_occurrence_velocity

Engine + analytics in one compose

The Docker demo ships more than the core engine — segment evaluation, pattern mining, and an Admin UI so you can explore fraud signals without writing glue code first.

Admin UI

Signals, Schema & Graph Explorer

Visual admin for schema design, Cypher Editor, Graph Explorer, and Analytics — Signals, Segmentation, Pattern Monitor, and anomaly views over the live graph.

Cypher Editor Signals Graph Explorer
segment-evaluator

Real-Time Segmentation

Evaluate entity membership against configurable graph signals as events stream in. Update segment rules live — no engine restart required.

velocity novelty neighbor_risk
pattern-miner

Pattern Mining

Mine merchant and sequence patterns (e.g. NEXT_MERCHANT) from live edges. Surface recurring fraud paths in Pattern Monitor without custom batch jobs.

NEXT_MERCHANT sequence rules live config

From zero to first
fraud signal in minutes

The jetgraph-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 jetgraph-client to your Cargo.toml and connect in seconds.

2

Register your schema

Declare node types, edge types, velocity windows, and property schemas once at startup — cards, merchants, devices, IPs, and more.

3

Query → Enrich → Insert

Follow the three-phase pattern on every event. Collect graph signals, apply your logic, record the outcome.

🦀

Rust Client

Native crate with typed API

🐍

Python Client

Protobuf gRPC bindings

🔤

Cypher HTTP API

openCypher subset — any language

🔌

Bolt Drivers

Compatible Neo4j drivers (subset)

Example — score a card transaction
score_transaction.rs
// Fraud scoring example — 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?; }

Up and running in 3 minutes

Try JetGraph locally with Docker — no build required. The demo compose starts the engine, segment-evaluator, pattern-miner, and Admin UI. Connect via openCypher HTTP, Bolt (port 7687, supported subset), or the visual analytics UI.

01

Start the stack

Save the file below as docker-compose.yml, then run docker compose up -d. Both images are pulled automatically from Docker Hub.

docker-compose.yml
services: graphengine: image: alhascan/jetgraph-demo:latest restart: unless-stopped ports: - "8080:8080" - "7687:7687" volumes: - graphengine-data:/data environment: RUST_LOG: info ENABLE_ADMIN_RESET: "true" healthcheck: test: ["CMD", "sh", "-c", "curl -sf http://localhost:8080/health || curl -sf http://localhost:8080/api/health || exit 1"] interval: 10s timeout: 5s retries: 5 start_period: 120s segment-evaluator: image: alhascan/jetgraph-demo:latest entrypoint: ["/usr/local/bin/segment-evaluator"] restart: unless-stopped environment: RUST_LOG: info GRAPH_ENGINE_ENDPOINT: http://graphengine:50051 SEGMENT_EVALUATOR_CONFIG_DB: /data/seg-config volumes: - seg-config-data:/data/seg-config depends_on: graphengine: condition: service_healthy pattern-miner: image: alhascan/jetgraph-demo:latest entrypoint: ["/usr/local/bin/pattern-miner"] restart: unless-stopped environment: RUST_LOG: info GRAPH_ENGINE_ENDPOINT: http://graphengine:50051 PATTERN_MINER_CONFIG_DB: /data/pm-config PATTERN_MINER_ADDR: 0.0.0.0:8082 volumes: - pm-config-data:/data/pm-config depends_on: graphengine: condition: service_healthy graphengine-ui: image: alhascan/jetgraph-ui-demo:latest restart: unless-stopped ports: # Change 80 to any free host port (e.g. "8081:3000") if port 80 is already in use - "80:3000" environment: BOLT_URL: bolt://graphengine:7687 NEO4J_USER: "" NEO4J_PASSWORD: "" GRAPH_HTTP_URL: http://graphengine:8080 SEGMENT_API_URL: http://segment-evaluator:8081 PATTERN_MINER_URL: http://pattern-miner:8082 depends_on: graphengine: condition: service_healthy volumes: graphengine-data: seg-config-data: pm-config-data:
02

Verify the engine is ready

Once both containers are up, check the health endpoint. You should see a JSON response with "ready":true. If you changed the UI host port in the compose file, open http://localhost:<your-port> instead of http://localhost.

bash
# Health check curl http://localhost:8080/health # → {"status":"ok","ready":true} # Then open the admin UI in your browser # If you changed the UI host port (e.g. "8081:3000"), use http://localhost:8081 instead open http://localhost
03

Load sample data with one click

Open the Admin UI at http://localhost, go to Schema in the left nav, and click Apply Schema & Load Sample Data. This provisions the Credit Card Fraud schema and seeds a representative dataset so every query in Analytics returns results — no manual Cypher required. Prefer to bring your own schema? Skip this step and use the manual flow in Step 05.

Admin UI flow
# 1. Open the UI open http://localhost # 2. In the left sidebar, click Schema # 3. In the "Quick Start — Credit Card Fraud Space" card, # click ⚡ Apply Schema & Load Sample Data # 4. When the green "All done" banner appears, explore in: # Graph Explorer (visual traversal) # Cypher Editor (free-form queries) # Analytics ▸ Signals / Patterns / Segmentation
04

Connect via Bolt (compatible drivers)

JetGraph listens on port 7687 with Bolt. Neo4j-compatible drivers work for the supported openCypher subset — no credentials required in demo mode. Full Neo4j Cypher is not guaranteed.

Python — neo4j driver
Node.js — neo4j driver
from neo4j import GraphDatabase driver = GraphDatabase.driver("bolt://localhost:7687", auth=("", "")) with driver.session() as session: result = session.run("MATCH (c:CARD) RETURN c.external_id AS id LIMIT 10") for record in result: print(record["id"]) driver.close() # → card-001
05

Or — register your own schema & run Cypher queries

If you skipped Step 03, declare your schema manually before writing data. Run these calls via the Cypher HTTP API — or paste them directly into the Cypher Editor in the UI.

bash — POST /cypher
# 1. Register node types (use 'string' for human-readable IDs) curl -sS -X POST http://localhost:8080/cypher \ -H 'Content-Type: application/json' \ -d '{"query":"CALL db.registerNodeType(\"CARD\", \"string\") YIELD node_type_id RETURN node_type_id","parameters":{}}' # Repeat for each type you need: MERCHANT, CUSTOMER, DEVICE, IP … curl -sS -X POST http://localhost:8080/cypher \ -H 'Content-Type: application/json' \ -d '{"query":"CALL db.registerNodeType(\"MERCHANT\", \"string\") YIELD node_type_id RETURN node_type_id","parameters":{}}' # 2. Register a relationship type curl -sS -X POST http://localhost:8080/cypher \ -H 'Content-Type: application/json' \ -d '{"query":"CALL db.registerEdgeType({name:\"TRANSACTS_AT\",from_node_type:\"CARD\",to_node_type:\"MERCHANT\"}) YIELD edge_type_id RETURN edge_type_id","parameters":{}}' # 3. Finalize schema — required before any write can succeed curl -sS -X POST http://localhost:8080/cypher \ -H 'Content-Type: application/json' \ -d '{"query":"CALL db.finalizeSchema() YIELD schema_version RETURN schema_version","parameters":{}}' # 4. Create nodes curl -sS -X POST http://localhost:8080/cypher \ -H 'Content-Type: application/json' \ -d '{"query":"CREATE (c:CARD {external_id: $id}) RETURN c.external_id AS created","parameters":{"id":"card-001"}}' # 5. Query back curl -sS -X POST http://localhost:8080/cypher \ -H 'Content-Type: application/json' \ -d '{"query":"MATCH (c:CARD {external_id: $id}) RETURN c.external_id AS id","parameters":{"id":"card-001"}}' # → {"columns":["id"],"rows":[["card-001"]]}

Explore visually in the Admin UI

Cypher Editor, Schema, Graph Explorer, plus Analytics — Signals, Segmentation, and Pattern Monitor.

http://localhost

Ready to add real-time fraud graph intelligence?

Get JetGraph running in minutes with Docker — single-node engine, analytics services, and Admin UI for the decision path.

$
docker compose up -d