← all features

Graph · live examples

Relations are first-class rows.

Edges live in the same substrate as the rows they connect — declared in the schema, written atomically with the data, traversed with prefix scans. Below: the traversal toolkit, a nine-motif library covering the structural patterns AML teams actually hunt, and the planner's guaranteed cardinality upper bounds (LP-based) pricing every pattern before a single edge is walked.

01
Declare
Relations are declared in the manifest and maintained bidirectionally on every write.
02
Traverse
Neighbors, BFS, paths, Cypher patterns — all prefix scans, no graph sidecar to sync.
03
Bound
Guaranteed cardinality upper bounds price every pattern before execution — the plan can never be surprised.
checking instance…one substrate · sql / graph / vector / fts / nql
Traversals & algorithms
01

Neighbors

easy

Accounts owned by one customer — forward edges of `owns`.

request
GET /v1/tenants/:t/graph/bank/neighbors?rel=owns&node=CUST-0042&limit=10
02

Reverse edges

easy

Who sent money INTO this account — reverse direction, same index, no extra write.

request
GET /v1/tenants/:t/graph/bank/neighbors?rel=txn_to&node=ACC-1877&direction=reverse&limit=10
03

BFS — blast radius

easy

Everything within 3 hops of a flagged account. The first question every investigator asks.

request
GET /v1/tenants/:t/graph/bank/bfs?rel=txn_to&start=ACC-0954&depth=3
04

Shortest path

easy

Are these two suspect customers connected at all? Path through owns + txn_to.

request
GET /v1/tenants/:t/graph/bank/path?from=CUST-0042&to=CUST-0163&rels=owns,txn_to&max_depth=6
05

Dijkstra — cheapest money route

intermediate

Weighted shortest path: the route between two accounts that moves money at the lowest total transfer cost.

request
GET /v1/tenants/:t/graph/bank/dijkstra?rel=txn_to&src=ACC-2201&dst=ACC-1120&weights_json=%7B%22field%22%3A%22fee_inr%22%7D
06

All simple paths — every route

intermediate

Not just one path: EVERY loop-free route money can take between two suspect accounts within 5 hops.

request
GET /v1/tenants/:t/graph/bank/all_simple_paths?rel=txn_to&src=ACC-2201&dst=ACC-1120&max_depth=5
07

PageRank — find the hub

intermediate

Rank accounts by transaction-graph centrality. The planted fraud ring's mule account surfaces on top.

request
GET /v1/tenants/:t/graph/bank/pagerank?rel=txn_to&limit=5
Motif library — nine laundering patterns
08

Motif 1/9 — Fan-out (smurfing)

easy

One account spraying funds to many receivers in a window — structuring deposits below reporting thresholds.

request
POST /v1/tenants/:t/cypher
{
  "query": "MATCH (a)-[:txn_to]->(b) WHERE a.out_degree_7d >= 15 RETURN a.account_id, a.out_degree_7d ORDER BY a.out_degree_7d DESC LIMIT 5",
  "default_schema": "bank"
}
09

Motif 2/9 — Fan-in (collection mule)

easy

Many senders converging on one receiving account — the collection side of a mule operation.

request
POST /v1/tenants/:t/cypher
{
  "query": "MATCH (a)-[:txn_to]->(m) WHERE m.in_degree_7d >= 15 RETURN m.account_id, m.in_degree_7d ORDER BY m.in_degree_7d DESC LIMIT 5",
  "default_schema": "bank"
}
10

Motif 3/9 — Reciprocal pair (ping-pong)

easy

A → B and B → A within days — value bounced to fake activity or reset trails.

request
POST /v1/tenants/:t/cypher
{
  "query": "MATCH (a)-[:txn_to]->(b)-[:txn_to]->(a) WHERE a.account_id < b.account_id RETURN a.account_id, b.account_id LIMIT 5",
  "default_schema": "bank"
}
11

Motif 4/9 — Wedge (one-step layering)

easy

A → B → C where A never touches C directly — the minimal layering hop that breaks naive pair-matching.

request
POST /v1/tenants/:t/cypher
{
  "query": "MATCH (a {flagged: true})-[:txn_to]->(b)-[:txn_to]->(c) RETURN a.account_id, b.account_id, c.account_id LIMIT 5",
  "default_schema": "bank"
}
12

Motif 5/9 — Triangle (round-trip)

intermediate

A → B → C → A. Money that comes home in three hops — the classic wash cycle.

request
POST /v1/tenants/:t/cypher
{
  "query": "MATCH (a)-[:txn_to]->(b)-[:txn_to]->(c)-[:txn_to]->(a) WHERE a.flagged = true RETURN a.account_id, b.account_id, c.account_id LIMIT 5",
  "default_schema": "bank"
}
13

Motif 6/9 — 4-cycle (extended round-trip)

intermediate

Four hops back to the origin — one more layer than the triangle, much harder to eyeball in statements.

request
POST /v1/tenants/:t/cypher
{
  "query": "MATCH (a)-[:txn_to]->(b)-[:txn_to]->(c)-[:txn_to]->(d)-[:txn_to]->(a) WHERE a.flagged = true RETURN a.account_id, b.account_id, c.account_id, d.account_id LIMIT 5",
  "default_schema": "bank"
}
14

Motif 7/9 — Scatter-gather

intermediate

Source fans out to intermediaries which all converge on a different destination — split, launder, reassemble.

request
POST /v1/tenants/:t/cypher
{
  "query": "MATCH (src)-[:txn_to]->(mid)-[:txn_to]->(dst) WHERE src.out_degree_7d >= 10 AND dst.in_degree_7d >= 10 AND src.account_id <> dst.account_id RETURN src.account_id, dst.account_id, count_distinct(mid) AS lanes LIMIT 5",
  "default_schema": "bank"
}
15

Motif 8/9 — Gather-scatter

intermediate

The mirror image: many sources pool into one account which then redistributes — pooling before dispersal.

request
POST /v1/tenants/:t/cypher
{
  "query": "MATCH (src)-[:txn_to]->(hub)-[:txn_to]->(dst) WHERE hub.in_degree_7d >= 10 AND hub.out_degree_7d >= 10 RETURN hub.account_id, hub.in_degree_7d, hub.out_degree_7d LIMIT 5",
  "default_schema": "bank"
}
16

Motif 9/9 — Mule chain (deep layering)

intermediate

A 4+ hop chain through low-activity accounts — each intermediary used once or twice, exactly why chains beat pair rules.

request
POST /v1/tenants/:t/cypher
{
  "query": "MATCH (a {flagged: true})-[:txn_to]->(m1)-[:txn_to]->(m2)-[:txn_to]->(m3)-[:txn_to]->(dst) WHERE m1.txn_count_30d <= 3 AND m2.txn_count_30d <= 3 AND m3.txn_count_30d <= 3 RETURN a.account_id, m1.account_id, m2.account_id, m3.account_id, dst.account_id LIMIT 5",
  "default_schema": "bank"
}
Bounded planning — guaranteed cardinality
17

Guaranteed upper bound vs naive estimate

intermediate

Before executing the triangle motif, the planner computes a GUARANTEED cardinality upper bound (LP-based — it can never lie low). Compare bound vs naive estimate vs what actually came back.

request
POST /v1/tenants/:t/cypher?explain=1
{
  "query": "MATCH (a)-[:txn_to]->(b)-[:txn_to]->(c)-[:txn_to]->(a) RETURN a.account_id LIMIT 100",
  "default_schema": "bank"
}
18

Bound-driven join order — 4-hop chain

intermediate

A 4-hop money-flow chain has many join orders. The planner prices each with guaranteed bounds and picks the cheapest — shown with the losing orders' bounds.

request
POST /v1/tenants/:t/cypher?explain=1
{
  "query": "MATCH (c)-[:owns]->(a)-[:txn_to]->(m)-[:txn_to]->(x)-[:txn_to]->(dst {flagged: true}) RETURN c.customer_id, dst.account_id LIMIT 50",
  "default_schema": "bank"
}