LEYLINE V3 · in progress
—Product

One engine, four decisions.

The homepage says what Leyline does. This is how, including the parts that are designed but not yet built. Where a figure is a target rather than a measurement, it says so.

01Execution

The planner picks where, never what.

Every query runs the same vectorized executor. What changes between a point lookup and a terabyte scan is how wide it spreads, and the planner decides that from the bytes a query will actually read after pruning, before it reads any of them.

It prefers the cheapest tier that can hold the query, because a lookup that started a worker would cost a hundred times what it should. If a tier turns out to be too small mid-flight, the query escalates rather than failing.

T0
In the service, no worker
up to ~64 MB to scan, one exchange at most
Point lookups, key anchors, indexed seeds, and small traversals answer inside the service process. No worker is invoked and no fleet cost is incurred, which is what lets a lookup cost the same on a large graph as on a small one.
answers intens of ms
T1
One worker, whole engine
up to ~4 to 8 GB
Mid-size traversals, filters and aggregates get a single worker running the same executor as every other tier. It streams its result back rather than assembling it in memory first.
runs onone function
T2
A fleet, then nothing
larger, or more than one exchange round at size
The worker count is derived from the bytes left after pruning, roughly one worker per 3 GB, clamped to a per-graph and per-account cap. A terabyte lands somewhere around 300 to 400 workers.
1 TB spreads to~300 to 400
02Storage

Statistics come free, so indexes stay optional.

Data is stored in node groups: a contiguous range of node ids with its property columns, its forward and reverse adjacency, and its statistics, targeting about 128 MB each. The group is the unit of pruning, of parallelism, and of compaction all at once.

Every writer records min, max, null count and value count per column chunk as it goes, because the data is already in memory at write time. That costs a few kilobytes and means the statistics are never stale. The planner reads them, discards the groups that cannot match, and only then opens anything.

No query is refused for lack of an index
An unindexed WHERE n.year = 2024 prunes every group whose range excludes 2024, then reads only the year column of what survives. Snowflake serves its entire workload this way.
An index is a file, not a rewrite
Declaring one writes a sorted run per node group as a separate committed artifact. Building it reads only that one column: about a minute for 50 GB, one to two for a terabyte. Your data is never rewritten.
Indexes degrade per group, not all at once
A group either has the run and gets seeded from it, or falls back to its own statistics and gets pruned. The planner can see which, so a half-built index is still useful.
What still earns one
Point and top-k access on high-cardinality properties, where ranges prune badly on unsorted data. Lookup keys and sort keys. Everything else rides the statistics.
03Writes

Writes land independently and commit together.

Each write is a record put to a log on its own, with no coordination and nothing to conflict over. A committer folds every record from a window into delta objects and one compare-and-swap on the manifest, so the expensive part happens once per window rather than once per write.

The design target is around a thousand writes per second per graph, with a path to ten times that. It is not a bulk-load-only store you refresh overnight, and it is not a queue pretending to be a database.

Two classes, acknowledged differently
An unconditional upsert or delete is validated before it is acknowledged and then acked at log durability with a sequence number. Anything whose answer depends on the graph, like MERGE, waits for the fold to resolve it, because the answer does not exist until then.
Read your own writes
The read path exposes how far the fold has got. A reader that needs to see a specific write waits on that watermark rather than guessing.
Ordering, stated plainly
Two writes to the same key in one window fold in log-sequence order. Acquiring the sequence is the ordering, and there is no wall-clock guarantee beyond it. Callers who need compare-and-set use the class that waits.
04Language

openCypher, graded by what can afford to run it.

The subset was frozen not out of conviction but because the old executor could not afford more. Joins, expressions and grouping were refused because they meant materializing everything in a small function, not because they are wrong for a graph.

Each wave below rides machinery being built anyway, and coverage is measured against the openCypher TCK, roughly 2,400 scenarios. The number gets reported rather than described.

A few things are permanently out: stored procedures, user-defined functions, LOAD CSV, and multi-statement transactions. The batch is the transaction.

  1. NOW

    What runs today

    Linear MATCH chains, one label per node, single ORDER BY key, literal-versus-property comparisons. Roughly 15 to 20% of the openCypher TCK. This is the honest number and it is the one we track.

  2. WAVE A

    Expressions

    The full expression grammar: arithmetic, string operations, CASE, list and map literals, null semantics, scalar functions, property-to-property comparison, multi-key ORDER BY, count(DISTINCT). Rides the vectorized evaluator, and roughly doubles coverage on its own.

  3. WAVE B

    Pipeline shapes

    WITH, implicit grouping, UNWIND, UNION. Each WITH boundary is a pipeline breaker, which is also a natural fleet stage boundary, so these map better onto scatter-gather than onto what came before.

  4. WAVE C

    Graph shapes and paths

    Branching patterns, repeated variables, OPTIONAL MATCH, EXISTS, undirected match, multi-label, path values, label-constrained closure and shortestPath. Reordered ahead of the rest in August 2026 once workload evidence showed recursion is what people actually run.

  5. WAVE D

    Writes

    MERGE with ON CREATE and ON MATCH, SET on edges, REMOVE, property expressions in SET, FOREACH. MERGE folds into the group committer as a write whose answer depends on graph state.

05Status

Designed, and partly built.

The transactional half works. The storage format, the planner and the fleet protocol are specified and under construction, and this page describes the design rather than a shipped product. The docs are specific about which is which.