A Rust graph database backed by redb.
cozo-redbis a Rust-first fork of cozodb/cozo — Ziyang Hu's transactional Datalog database. It keeps the query language, Datalog semantics, time-travel relations, and HNSW vector search, and uses redb (a pure-Rust mmap B-tree) as its single persistent backend.This fork ships only the
memandredbbackends; rocksdb, sled, sqlite, tikv, and the non-Rust language bindings are gone. For other notes, see DIFFERENCES.md.If you have never met Cozo before and would like a walked-through explanation — what Datalog is, how rules and stored relations fit together, why recursion is the whole point, and what time travel, vector search, and full-text search look like in the concrete — read SERMON.md. It is the in-depth introduction the cozo lineage never quite got around to writing.
No support commitment, no release cadence promise. MPL-2.0, PRs welcome.
- Introduction
- Getting started
- Install
- Architecture
- Status of the project
- Links
- Licensing and contributing
cozo-redb is — and I always say this to anyone who will listen, though
there are fewer of them these days than one might wish — an embedded,
transactional database, which is only a fine way of saying that it lives
quietly in the same room as the program it serves, and does not go
shouting at it from another house altogether. It is queried in Datalog
(a language, I am assured by those who know about such things, of
considerable cleverness and long pedigree), and it keeps relational,
graph, and vector data all under the one roof — which I always think is
much the most sensible arrangement, for I cannot abide a household in
which everything is scattered about in different rooms. It remembers,
too, what it used to know — time travel, they call it, though it is
nothing more alarming than a well-kept diary — and it stores all its
affairs in a single tidy file by means of redb, which is, I am told,
a pure-Rust mmap B-tree; and whilst I could not pretend to explain what
that is, I am quite sure it is a very respectable thing indeed.
A Rust crate that runs in your program's process. No server, no socket,
no daemon, no port to open. Add cozo to your Cargo.toml, call it
from your code, ship one binary.
Most interesting questions about data are questions about relationships:
who connects to whom, what leads to what, how far apart two things are.
SQL can express them, but recursive traversals are awkward and slow.
cozo-redb stores data in ordinary relations and queries them with
Datalog, which handles recursion natively — shortest-path, reachability,
and PageRank are one query, not twenty.
This is not a labelled-property graph database. There are no nodes-and-edges primitives. Model your data as relations; the graph is whatever the relations describe.
Queries are composed from named rules, not nested subqueries. Recursion
is first-class — a rule may refer to itself — so graph traversals and
transitive closures are written directly, without WITH RECURSIVE
gymnastics. Anything SQL can express, Datalog can express, usually more
cleanly.
Every relation may track its own history. Updates don't overwrite — they append a new version tagged with a validity time. Queries can then ask "what did this relation look like last Tuesday?" and get the Tuesday answer.
It costs storage and a little query overhead, so it is opt-in per relation. If a relation doesn't need history, don't enable it.
This fork targets embedded, single-box workloads. On the retired multi-backend version,
benchmarks (cozo-core/BENCHMARKS.md) showed redb beating sqlite on every read and
aggregation workload by 32–49%, with time-travel aggregation over a 1M-row relation
2.35× faster, which is why redb was kept as the sole persistent backend.
The query language reference (tutorial, execution model, built-in functions) is still hosted at the original upstream docs site — this fork has not replicated it. Start with the tutorial, then see the execution model. Most of what is described there still applies to this fork's query engine, but mind that the full-text index has been modified and MinHash-LSH has been removed altogether; the upstream pages covering those are no longer accurate here.
If you are in a hurry and just want a taste of what querying with CozoDB is like, here it is.
In the following *route is a relation with two columns fr and to,
representing a route between those airports,
and FRA is the code for Frankfurt Airport.
How many airports are directly connected to FRA?
?[count_unique(to)] := *route{fr: 'FRA', to}
| count_unique(to) |
|---|
| 310 |
How many airports are reachable from FRA by one stop?
?[count_unique(to)] := *route{fr: 'FRA', to: stop},
*route{fr: stop, to}
| count_unique(to) |
|---|
| 2222 |
How many airports are reachable from FRA by any number of stops?
reachable[to] := *route{fr: 'FRA', to}
reachable[to] := reachable[stop], *route{fr: stop, to}
?[count_unique(to)] := reachable[to]
| count_unique(to) |
|---|
| 3462 |
What are the two most difficult-to-reach airports
by the minimum number of hops required,
starting from FRA?
shortest_paths[to, shortest(path)] := *route{fr: 'FRA', to},
path = ['FRA', to]
shortest_paths[to, shortest(path)] := shortest_paths[stop, prev_path],
*route{fr: stop, to},
path = append(prev_path, to)
?[to, path, p_len] := shortest_paths[to, path], p_len = length(path)
:order -p_len
:limit 2
| to | path | p_len |
|---|---|---|
| YPO | ["FRA","YYZ","YTS","YMO","YFA","ZKE","YAT","YPO"] |
8 |
| BVI | ["FRA","AUH","BNE","ISA","BQL","BEU","BVI"] |
7 |
What is the shortest path between FRA and YPO, by actual distance travelled?
start[] <- [['FRA']]
end[] <- [['YPO]]
?[src, dst, distance, path] <~ ShortestPathDijkstra(*route[], start[], end[])
| src | dst | distance | path |
|---|---|---|---|
| FRA | YPO | 4544.0 | ["FRA","YUL","YVO","YKQ","YMO","YFA","ZKE","YAT","YPO"] |
CozoDB attempts to provide nice error messages when you make mistakes:
?[x, Y] := x = 1, y = x + 1
eval::unbound_symb_in_head × Symbol 'Y' in rule head is unbound ╭──── 1 │ ?[x, Y] := x = 1, y = x + 1 · ─ ╰──── help: Note that symbols occurring only in negated positions are not considered bound
This fork targets Rust embedders.
- Rust library: add
cozoto yourCargo.tomlvia the workspace crate incozo-core/. Default features arecompact=storage-redb+requests+graph-algo; that's almost certainly what you want. - Standalone binary (
cozo-bin/): CLI and REPL for ad-hoc queries against a redb database file. Build withcargo build --release -p cozo-bin. - WebAssembly (
cozo-lib-wasm/): in-browser build viawasm-pack, exposing aCozoDbJS class backed byMemStorage. Full-text search works in the browser too, via an in-RAM tantivy index. Seecozo-lib-wasm/build.sh— cross-compiling thezstd-sysshim requires a wasm-capable clang (apt install clang-19on Debian).
CozoDB consists of three layers stuck on top of each other, with each layer only calling into the layer below:
| (User code) |
| Language/environment wrapper |
| Query engine |
| Storage engine |
| (Operating system) |
The storage engine defines a Storage trait — a key-value interface over binary blobs
with range scan — and two implementations that plug into it: in-memory (for tests
and the WASM build) and redb (the single persistent backend).
Keys are encoded using a memcomparable format so that byte-wise lexicographic ordering matches the intended row ordering.
The query engine owns function/aggregation/algorithm definitions, the schema, the transaction layer, query compilation and execution. Embedders interact with it via the Rust API. The query language reference lives in the original upstream execution docs.
cozo-redb exists so I have a tight, pure-Rust graph database in my personal toolkit.
MPL-2.0, PRs and issues welcome if you are using it.
Versions before 1.0 do not promise syntax/API stability or storage compatibility. For the fork's scope and what has been trimmed from upstream, see DIFFERENCES.md.
- Fork repo — this repository
- Upstream repo (dormant) — the original CozoDB
- Upstream query language docs — tutorial, execution model, built-in functions (mostly accurate for this fork; full-text has been modified and MinHash-LSH removed)
- Rust API docs — generated from upstream's last release; this fork's docs land on docs.rs after a release
This project is licensed under MPL-2.0 or later. See CONTRIBUTING.md if you are interested in contributing.