Pre-v0 Rust database engine

Graph, vector, and typed data in one local engine.

ffs is an experimental database engine for applications that scan, traverse, search embeddings, and write derived state back without stitching together separate stores too early.

ffs.db local engine
Cypher subset HNSW vector search typed column groups CSR graph edges MVCC + WAL
Shape
embedded Rust crate
Atomicity
one WAL, one transaction
Status
347 tests passing
Graph traversal relationships share the same engine as the records they connect
Vector similarity embedding search beside the data it indexes
Write-back derived records keep source links and commit atomically

Some workloads should not need three databases on day one.

Graph traversal, vector search, typed records, and provenance often start in separate systems. That can be the right answer at scale, but it also adds glue, duplicate indexes, and extra places for write paths to drift.

ffs explores a smaller local engine first. The app opens a file. Graph edges, vectors, typed properties, and provenance records share the same buffer pool, WAL, catalog, and commit boundary.

Built for local data movement.

ffs favors the paths where data has to move through several shapes: scan columns, expand relationships, search embeddings, check schema, write back, and recover after a crash.

querytyped Cypher subset
executionoperators + morsels
indexesB+-tree + HNSW
storagenode groups + CSR rels
durabilityMVCC, pager, WAL, catalog
01

Typed graph storage

Columnar node groups and CSR relationship tables for cache-friendly traversal.

02

Vector index

HNSW search is in tree today, with durable index layout still being shaped.

03

Schema boundary

Types are checked before bad data reaches disk, not cleaned up in app code.

04

MVCC and WAL

Snapshot isolation and crash recovery across graph, vector, and facts.

05

Cypher subset

Graph-native pattern matching, with read and mutation paths in tree.

06

Provenance API

Derived nodes can carry source links and confidence as first-class data.

Benchmarks for selected hot paths.

The eval harness compares in-process reads, vector search, graph traversal, and server-stack overhead. The point is not a final scorecard; it is a way to keep design decisions measurable.

Comparator Path Result
sled KV lookup 1.8x faster
instant-distance HNSW query 2.6x faster
petgraph 1-hop traversal 9x faster
pgvector HNSW query 3.01x faster

Open a graph. Traverse it. Keep the data path local.

use ffs::cypher::{compile_query, parse};
use ffs::exec::collect_column;
use ffs::planner::{compile, CompileCtx};
use ffs::storage::RelTable;

let mut knows = RelTable::new(0, "KNOWS", 4, 4);
knows.add_edge(0, 0, 1, 1);
knows.add_edge(0, 0, 2, 2);

let q = parse("MATCH (a:Person)-[:KNOWS]->(b:Person) RETURN b")?;
let plan = compile_query(&q, |_| vec![0, 1, 2, 3]);
let ctx = CompileCtx::empty().with_rel_table("KNOWS", &knows);
let mut op = compile(plan, &ctx)?;
let neighbours = collect_column(&mut *op, 0);

Pre-v0, with the spine already in tree.

ffs is early. The storage spine, transactions, schema and type system, pager-backed catalog, B+-tree indexes, in-memory HNSW, Cypher parser/planner, executor, and Python binding work are in the repo.

  1. Now close/reopen mixed workloads, vector persistence, SQL compatibility track
  2. Next cost-based planner, secondary index persistence
  3. Later broader bindings, server wrapper only if embedded earns it