Against Kùzu and DuckDB on the LDBC SNB reads — and against Memgraph and Neo4j on the Pokec social graph — Lattice wins every interactive query, from a 33 µs point lookup to a two-hop traversal. It pays for that with a larger store and, at the largest scale, a slower load. Here is the whole picture, wins and trade-offs together.
Median latency over 200 random Person.id parameters, prepared statements, measured
uniformly through Python so per-call overhead is identical for all three. Lower is better; the axis
is logarithmic because the engines are orders of magnitude apart.
The multi-hop reads, once the weak spot, now lead too. "Friends' messages" and the variable-length 2-hop were 3–19× behind at the first comparison; late materialization, a batched frontier expand, and serving checkpointed pages straight from cache turned them into wins at every scale.
The honest counterweight. Load is the whole "ready to serve" cost — parse, bulk build, index, checkpoint. Lattice wins load at SF1 and SF10 — beating both Kùzu and DuckDB — and trails only Kùzu at SF100 (11.9 s vs 5.8 s), where the bulk build writes the bidirectional CSR adjacency the traversal wins above are built on. On disk it stays within 1.15× of Kùzu at every scale. A load-vs-query trade, by design.
The real Pokec-medium social graph (100k users, 1.77M edges), same Cypher string on each engine over Bolt. Lattice takes every pattern and traversal query, wins scan-and-return, and — after two-phase parallel aggregation — sweeps whole-graph aggregation too, up to 10× ahead. On single-statement writes it wins durably against Neo4j (3–4×) and, at the same durability level, against non-durable Memgraph too (relaxed mode, 1.3–11×) — uniquely offering both full durability and Memgraph-class latency. Every tab below is real Pokec data, answers proven identical.
Truespar Traverse is a new in-memory graph database — Bolt + Cypher, like Memgraph, held entirely in RAM. Its free tier caps at 10,000 nodes / 50,000 edges, so this panel is a smaller Pokec cut — 9,000 users, 45,000 edges — run on all four engines at that scale for a fair comparison (the 100k charts above exceed Traverse's ceiling). Same Cypher, answers proven identical. Lattice — embedded and on-disk — takes every query: every seeded pattern and traversal (~20× ahead, no socket to cross), every whole-graph aggregation, and every scan — including the filtered and multi-hop counts an in-memory engine would be expected to own, because Lattice answers them from node degrees and edge-pair statistics rather than walking (see the Scan tab). Being embedded pays off under load too: concurrent point reads run ~20× Traverse's over Bolt (31k vs 1.5k ops/s, a single client). Concurrent writes can't be put on the same axis at all — a sustained write burst exceeds Traverse's 10,000-node cap and drops the server; the Lattice write-throughput story is the 100k section below (relaxed 11.7k writes/s, past every engine).
Throughput, not latency: a 3-second burst of point reads or vertex creates spread across N clients, in ops/second on the Pokec graph. Lattice is embedded — a client is a thread in the process, so a read never pays a socket — where Memgraph and Neo4j answer every op over Bolt. On writes it takes a single writer, but shows two lines: relaxed wins outright at every client count, and durable — crash-safe, one fsync per commit — still scales, because group commit batches those fsyncs, past non-durable Memgraph by 12 clients.
No cherry-picking. Two places the numbers go against Lattice, and why.
11.9 s vs Kùzu's 5.8 s — the one durable loss (SF1 and SF10 load are wins). The bulk build, most of it, writes the bidirectional CSR adjacency that makes traversals fast: more bytes at lower throughput. Clawing it back would cost the query lead.
1.70 GB at SF100 — 1.15× Kùzu, 1.67× DuckDB (and smaller than Kùzu at SF1). Integers are frame-of-reference compressed and strings dictionary-encoded; the bidirectional CSR is the deliberate remainder.