From core engine to public proof.
The labels describe sequence; none of them carry dates. Each entry says what should get better in plain English and what evidence has to exist before the claim goes public.
Releases
-
v2.0compute attaches to object storagein progress
The lakehouse release (2.0.0-alpha.1). The storage half is built: a database checkpoints one consistent generation to an S3-compatible object store, restores any retained generation, or attaches read-only with data pages served by ranged GETs — many readers on one checkpoint prefix, one local writer, with multipart upload, lazy attach, and checkpoint pins that hold an attached generation against retention. The compute half is underway: the typed columnar pipeline is converging on read parity with the in-memory evaluator. Still ahead: the read flip, typed mutations, the planner, and the product surfaces.
-
v1.0the disk engine is the engineshipped
Data and reads on the disk engine by default; the working set bounded by the unflushed tail; checkpoint-anchored opens replaying only the log suffix; crash-safe publishes; one legacy kill-switch for one release; open fails loud on corruption. The proof ladder passes under the release defaults at constant-rate ingest.
-
v0.5core existsshipped
Opens a database file, writes, reopens, verifies storage/qlog posture, runs Cypher, searches HNSW vectors, exposes ffsd commands. 920 passing tests and the local comparator evals.
-
v0.6trust + index hardeningdue
Fewer sharp edges on restart, import/export, schema backfills, secondary indexes, and vector-index maintenance. Proof: crash/reopen tests, index invariant checks, safer planner fallbacks.
-
v0.7execution speed passlater
Bigger scans, joins, traversals, sorts, and write-back paths do less row-at-a-time work. Speed claims wait until before/after numbers exist on measured workloads.
-
v0.8movement-aware plannerlater
The engine chooses where work happens: scan columns, use a B+-tree, expand graph edges, search vectors first, filter first, stream, materialize, or write back. Proof: EXPLAIN output that names movement cost.
-
v0.9write-back looplater
The signature workflow runs end to end in the engine — retrieve, traverse, derive, write back, update indexes, commit — with no sidecar processes stitched around it.
-
v0.10public proof ladderlater
Public, reproducible numbers against well-known systems, with raw commands, machine specs, and losses included. 10GB, 100GB, and 1TB-class ladders where feasible.
Storage convergence (v1)
Alongside the release labels, v1 moves the engine onto disk, stage by
stage (ADR 0021–0025 in the repo). The read side is
done: point reads, scans, BFS adjacency,
and MVCC snapshot visibility all serve from pager-backed structures
plus a dirty-tail overlay at ~3x of in-memory speed, proven equal
across the full Cypher surface and a reopen. The write side is
done: every read a write depends on serves
from the disk engine, edge state has its own pager file, the
MERGE/uniqueness index persists, and the storage substrate finished
its ladder — extents as recorded contracts, checkpoint-anchored
opens that replay only the log suffix, crash-safe publishes,
incremental O(dirty) flushes with threshold-paced checkpoints, and
epoch-pinned lock-free readers with extent recycling. Eviction is
done: the in-memory store holds exactly
the unflushed tail, and process memory is bounded by it. The typed
query pipeline is done for its read
surface (144 parity tests; every live shape ported or precisely
refused) and for the four-stage mutation ladder behind real
workloads. The proof ladder runs green at 256MB and 1GB with exact
crash recovery, including under the full disk-served defaults. The cut itself is
done: merged 2026-06-13 as v1.0.0 —
defaults on, ~1,100 lines of legacy deleted behind one kill-switch
(FFS_SPINE_LEGACY=1 restores the pre-cut world for one
release), open fails loud on corruption with a tested state matrix,
and the proof ladder green under the release defaults.
Object storage (v2)
The v2 storage half, landed 2026-06-13 as eight gated commits (ADR
0026 in the repo). The local engine keeps everything v1 built; an
object store holds immutable generation checkpoints
— the snapshot family, uploaded, with one root object written
last so a checkpoint exists only when complete. On top of that:
checkpoint_to uploads one consistent generation under
the same guard a snapshot holds; restore_from_checkpoint
materializes any retained generation (time travel is a passing
test); attach_checkpoint opens read-only directly
against the store, data pages served by whole-extent ranged GETs
through a cache — no image is ever downloaded whole. Retention
retires checkpoints root-first and a sweep collects torn uploads
without ever touching one in flight. Many readers attach to one
checkpoint prefix while one local writer keeps writing — proven
in concurrent tests. The server wires it as
--checkpoint-store / --checkpoint-retain
and a read-only --attach-store mode, and
ffs-s3 speaks SigV4 to AWS S3, MinIO, and R2 —
verified against the published AWS signing vectors, with S3's silent
range truncation surfaced as the error the attach contract requires.
Multipart upload for large objects is done
(a single PUT past S3's 5 GiB ceiling, parts assembled with an
If-None-Match conditional complete), truly-lazy attach is
done (a reader skips deriving the seed
indexes until a query needs them, with checkpoint pins keeping its
generation from being retired underneath it), and ffsd
drains and exits on SIGINT/SIGTERM. Writer
promotion/handoff — a fenced single-writer lease over the shared
prefix — is designed (ADR 0028) on the conditional-write
primitive now in the object-store trait.
Compute convergence (v2)
The v2 compute half (ADR 0029 in the repo). Two query engines exist
today: the in-memory evaluator that serves every production read, and
a typed columnar pipeline validated shape-by-shape against it. The
plan grows the typed pipeline to read parity under a shadow diff, then
flips reads onto it behind a kill-switch and retires the interpreter's
read path. Read parity is underway:
property and aggregate projections, scalar and numeric functions,
arithmetic, coalesce, and collect/list
results lower over both anchor and joined (hop-target, relationship)
columns. Measured against the product read surface, the typed path
matches the in-memory engine on every shape it lowers and the
interpreter serves the rest — zero divergence, the bar the read
flip waits on. Ahead: the read flip, typed mutations live, and a
planner-driven physical path.
Build phases
The engineering ladder behind the labels, from the repo's
ROADMAP.md. Each phase ends at an exit bar.
P0 — trust the core. Make the existing engine boringly correct: catalog recovery across close/reopen, WAL replay for mixed writes, page and index invariant checks, deterministic crash scenarios, fuzzed WAL decode and query parsing. Exit: kill/reopen tests are ordinary; every persisted structure has an invariant checker.
P1 — durable native indexes. Persist HNSW and secondary indexes as engine-native structures, define index rebuild vs WAL replay rules, add stats for planner selectivity, benchmark maintenance cost under writes. Exit: vector and secondary indexes survive restart; maintenance cost under writes is measured.
P2 — data movement execution. Finish HashJoin, IMJ, OrderBy, Distinct, and Union; thread morsel execution through scans, joins, traversal, and vector search; SIMD kernels where useful; bulk ingest and write-back paths. Exit: scan/filter/join/traverse/search/write-back run as one physical plan.
P3 — movement-aware planner. A shared physical-plan IR across surfaces; column, fanout, and vector-index stats; cost terms for scan vs lookup vs graph expansion vs vector search, including write amplification. Exit: plans are explainable; obvious bad plans are rejected by tests.
P4 — derived write-back loop. Bulk provenance write-back, embedding refresh APIs, write-back operators in the execution engine, one transaction across derived fact, provenance edges, embedding update, and index maintenance. Exit: the full loop runs without sidecar systems.
P5 — developer surfaces. Stabilize the Rust API for hot paths, improve Python ergonomics, open a SQL/Postgres compatibility track, add migration and inspection commands, typed failures with clear messages. Exit: a developer can open a file and build something useful in minutes.
P6 — proof. Comparator harness against SQLite, DuckDB, Postgres, Kùzu, Neo4j, LanceDB, Qdrant/pgvector, and RocksDB/sled, with published machine specs, commands, datasets, raw outputs, and losses; large workload ladders; crash-during-load scenarios. Exit: users can reproduce the numbers; FFS has a credible first arena where it is clearly better.
P7 — optional server wrapper. Only after the embedded engine earns it: TCP wire wrapper, auth and connection management, observability, backup and restore tooling, replication research. Exit: server mode does not fork the engine; embedded remains the reference path.