Two properties that usually exclude each other
Embeddability wants the engine to be your application's address space. Disaggregated storage wants durable state to live over the network so compute is stateless. Twill DB resolves the tension by moving the seam inward.
Truly embeddable
Links in-process as a native library over a frozen C ABI. The hot path is a function call, never a network round-trip — SQLite-style ergonomics, link it anywhere Bun, Node, or C can call.
Storage-disaggregated
Durability bottoms out on object storage (S3 / Cloudflare R2 / MinIO) via an LSM page store and an S3-CAS commit log. Compute holds no durable state, so it is disposable.
One pluggable seam
The engine never touches disk — it talks to a single narrow Storage trait. The backend is chosen by URL scheme: file:// embeds, s3:// disaggregates. No rebuild.
Instant branching
A branch is a cheap LSN pointer over shared immutable layers (copy-on-write). Fork a database in O(1); writes diverge into a private overlay and never touch the base.
Scale-to-zero
The lifecycle controller cold-starts on first connection and tears down when idle. At rest you pay only for object-storage bytes — no idle compute bill.
Postgres-wire compatible
The same engine runs behind a Postgres-wire listener. psql, Bun.sql, pgbench, and PostgREST connect unchanged — no bespoke driver, no bespoke REST layer.
Vector search in-core
A vector(N) type and an HNSW index live behind the same storage seam as the rows — so vector search branches and scales-to-zero with the database. An agent can fork its memory.
Snapshot isolation
MVCC throughout: every reader sees a stable snapshot and never blocks a writer, while a first-committer-wins check keeps concurrent transactions correct. One writer per database, lock-free reads.
Crash-safe durability
Commits are WAL-centric: every acked write is fsync-durable before the call returns — never acked from a buffer. Recovery replays the log deterministically and discards a torn trailing frame.
Open a database with a connection string
Build the native library once, then use the typed Bun wrapper. The backend is selected purely by the URL scheme — flip file:// to s3:// and the same code path becomes disaggregated and scale-to-zero, with no recompile.
Branching is a first-class operation: a branch sees the base's data and writes in isolation.
import { open } from "@twilldb/bun";
using db = open("file://./local.db"); // or "s3://bucket/db"
db.exec(`CREATE TABLE notes (id INTEGER PRIMARY KEY, body TEXT)`);
db.query("INSERT INTO notes VALUES (?, ?)", [1, "hello"]);
const rows = db.query("SELECT id, body FROM notes");
// [{ id: "1", body: "hello" }]
// Instant copy-on-write branch: sees the base, writes in isolation.
using preview = db.branch("preview");
preview.exec("INSERT INTO notes VALUES (2, 'branch-only')");
// the base never sees the branch's write
# The same engine, behind a Postgres-wire listener
cargo run -p twill-server -- \
--listen 127.0.0.1:5433 \
--db file://./srv.db # or s3://bucket/db
# Any Postgres client connects (cleartext):
psql "host=127.0.0.1 port=5433 user=postgres sslmode=disable"
Wrap the library in a wire listener
Server mode is the same library wrapped in a Postgres-wire listener — there is no second engine to maintain. Multi-client access, existing Postgres tooling, and connection pooling all come along for the ride.
Whether a caller reaches the engine through an FFI call or a network socket is the only thing that changes.
Four doors into the project
Use the database, follow the design intent, track what shipped and what's next, or meet the person behind it.
Documentation
User guides: how to connect, branch, pool, and operate the engine. Start here to build something.
Development guidelines
The fourteen design specifications and implementation maps — the source of truth for design intent.
Releases & roadmap
What's shipped and what's coming next — the capability milestones and what's planned.
The author
Who is building Twill DB and why — the philosophy and the quest behind the project.
"SQLite that forgot where its file was — and found it on S3."
Keep the in-process, link-it-anywhere ergonomics; point the storage backend at the network instead of a local file. Embeddable and disaggregated stop being contradictory the moment the seam is a pluggable backend rather than a server you connect to.
Analytics & cookies
This site uses Google Analytics 4 to understand which docs and specs are read, so we can improve them. Analytics only runs after you click Accept on the consent banner — until then no Google script loads and no analytics cookie is set. We default Google Consent Mode to "denied", request IP anonymisation, and never use the data for advertising. Your choice is stored locally in your browser; clearing site data resets it and the banner returns. The engine and your databases are wholly unaffected — this concerns the documentation website only.