FFS is a Rust database engine for graph, vector, and write-back workloads.

Typed records, relationship tables, embedding indexes, and provenance share one pager, one WAL, and one transaction boundary.

Every benchmark on this site reproduces from one cargo command, losses included.

Thirty seconds

$ cargo run -p ffs-demo --release

            pager           one file, 8 KiB pages, MVCC/WAL, catalog root
            schema          Person, KNOWS edge, Embedding(dim=4)
            rel table       6 KNOWS edges, A+ double CSR persisted
            primary index   on-disk B+-tree, 5 nodes
            Cypher          MATCH (n:Person) WHERE n.age > 30 RETURN count(n) → 3
            GNN sampler     2-hop batch over 5 anchors in 47 µs
            provenance      derived embedding written back with source link
            recovery        crash, reopen, replay, equal state

Every line runs in the same engine, against the same file. The traversal on line 5, the GNN sample on line 6, and the provenance write on line 7 sit inside one transaction — if line 7 fails, lines 5 and 6 don't commit.

Measured

PathffscomparatorResult
B+-tree insert, random u64429 nssled · 1241 nsffs 2.89x
HNSW query, 0.966 recall@10113 µsinstant-distance · 298 µsffs 2.64x
1-hop neighbour read11 nspetgraph · 102 nsffs 9.28x
CSR edge append30 nspetgraph · 3 nspetgraph 9.64x
15-seed BFS, depth 4, 35K nodes14 msper-seed driver loop · 68.8 sffs 4858x

One harness, one command, Apple M-series. The append row is a loss by design — gap-preserving CSR pays at write time and collects on every read. Every number, with caveats.

The loop

// vector candidates, then graph context
        MATCH (d:Dispute)
        WHERE d.embedding NEAR $claim TOP 5
        MATCH (c:Customer)-[:FILED]->(d)
        RETURN c.tier, d.amount, d.status

        // the decision goes back through the same qlog
        MATCH (d:Dispute {id: $id})
        SET d.triage = 'manual_review', d.matched_pattern = $pattern

This is the workload FFS is shaped around: an agent retrieves by embedding, expands through relationships, decides, and writes the decision back durably. In the usual stack those steps span Postgres, a vector store, and application glue. Here they span one transaction boundary.

Why this code exists

Modern heavy workloads do not just store records. They scan, retrieve, traverse, embed, derive, and write back continuously. Today that usually means a relational database for facts, a graph database for relationships, a similarity engine for embeddings, a queue for events, and application code keeping the IDs and indexes aligned.

At scale, each boundary adds latency, duplicate indexes amplify writes, and a cross-system query means serializing rows and joining them on IDs in application code. Most failures happen in that glue.

FFS brings the data path into one engine: one buffer pool, one WAL, one fsync discipline per commit. A graph update, a vector upsert, and the typed fact they support land in the same commit; if it aborts, none of them happened.

And yes, the name means what you think it means. It is what you say the third time the relational store, the vector index, and the graph database disagree about one record.

What it runs

ERP.ai, Neo Agent, Proto. The shared data path for thousands of apps and hundreds of thousands of agents: app state, agent memory, tenant context, graph relationships, vector retrieval, provenance, query history, and durable write-back in one engine.

Agent fleet query layer. Runtime reads for large agent fleets asking what an app knows, which entities are connected, what changed, which source produced it, and what should be retrieved next.

Operational write-back. ERP.ai-style workflows where approvals, disputes, procurement, finance, customer records, tool calls, and model outputs continuously read, derive, index, and write back state.

All six production use cases →

Install

$ curl -fsSL https://ffsdb.com/install.sh | sh
        $ ffsd --db ./my.ffs --create
        $ printf 'PING\n' | nc 127.0.0.1 7767
        OK pong

The script builds ffsd from a checkout when run inside one, otherwise clones the repo — ssh first, then https, prompts disabled — and ends in cargo install --path ffsd --locked. FFS is in private preview, so the clone needs access to the repository. The daemon answers line-oriented commands: PING, QUERY, LOAD_MANIFEST, SNAPSHOT, VERIFY, and the rest of HELP.

Status

v1 — done. The single-node disk engine shipped as v1.0.0 on 2026-06-13 and is the default: data and reads serve from the pager-backed engine, the working set is bounded by the unflushed tail, opens are checkpoint-anchored and replay only the log suffix, and one kill-switch (FFS_SPINE_LEGACY=1) restores the pre-cut engine for a release. The typed query pipeline covers its read surface and a four-stage mutation ladder, each shape proven against the live engine.

v2 storage — done. A database checkpoints one consistent generation to an S3-compatible object store and restores any retained generation, or attaches to one read-only with data pages served by ranged GETs rather than a whole-image download. ffs-s3 speaks SigV4 to AWS S3, MinIO, and R2, with multipart upload for large objects. Many readers share one checkpoint prefix while one local writer keeps writing; checkpoint pins hold an attached generation against retention while a reader is on it, attach is lazy, and ffsd drains and exits cleanly on a signal.

v2 compute — now (2.0.0-alpha.1). The typed columnar pipeline is reaching read parity with the in-memory evaluator so reads can serve from it. Property and aggregate projections, scalar and numeric functions, arithmetic, and collect/list results now lower over anchor and joined columns. Measured against the product read surface, the typed path matches the live engine on every shape it lowers and falls back to it on the rest — zero divergence — the bar the read flip waits on.

Later. Typed mutations and a planner-driven physical path; the catalog and the product surfaces (control plane, studio, flow); read sharing and distribution across attached compute. Then the larger-scale proof ladder — the first beyond-RAM rungs, then 10GB, 100GB, and up.

ffsdb.com — private preview next: engine →