Typed graph storage
Columnar node groups and CSR relationship tables for cache-friendly traversal.
Pre-v0 Rust database 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.
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.
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.
Columnar node groups and CSR relationship tables for cache-friendly traversal.
HNSW search is in tree today, with durable index layout still being shaped.
Types are checked before bad data reaches disk, not cleaned up in app code.
Snapshot isolation and crash recovery across graph, vector, and facts.
Graph-native pattern matching, with read and mutation paths in tree.
Derived nodes can carry source links and confidence as first-class data.
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 |
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);
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.