Quickstart
Build the engine once, open a database with a connection string, run SQL in-process from Bun, and then start the same engine as a Postgres-wire server. No infrastructure required for the embedded path.
Prerequisites
1 · Build the engine
Clone the repository and build the release libengine. This produces the static and dynamic libraries plus the frozen C ABI header.
git clone https://github.com/bihaviour/twill-db
cd twill-db
cargo build -p twill-engine --release
# → target/release/libengine.{a,so,dylib} + crates/engine/include/engine.h
When to rebuild
The Bun client loads the native library through bun:ffi. After any change that touches the C ABI or engine behaviour, rebuild the release libengine before running the client — otherwise it runs against a stale binary.
2 · Your first embedded database
The @twilldb/bun wrapper auto-discovers the library from target/{release,debug} (or set TWILLDB_ENGINE_PATH to an explicit path). Open a file:// database and run SQL at function-call latency.
// notes.ts
import { open } from "@twilldb/bun";
using db = open("file://./local.db"); // pure-embedded, zero network
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");
console.log(rows); // [{ id: "1", body: "hello" }]
cd clients/bun
bun install
bun run ../../notes.ts # or: bun run examples/notes.ts
bun test # the end-to-end embedded test suite
The database persists to ./local.db and is rebuilt by replaying the durable WAL on reopen, so your data survives a process restart.
3 · Go disaggregated (optional)
To make the same code path disaggregated and scale-to-zero, change only the connection string — no recompile, no code change.
using db = open("s3://my-bucket/notes"); // disaggregated; durable on object storage
Provide bucket credentials through the environment (never in code). See Connect to your database for the supported schemes and Scale-to-zero for the lifecycle.
4 · Start a server
Run the same engine behind a Postgres-wire listener and connect with any Postgres client (cleartext / sslmode=disable).
cargo run -p twill-server -- --listen 127.0.0.1:5433 --db file://./srv.db # or s3://bucket/db
psql "host=127.0.0.1 port=5433 user=postgres sslmode=disable"
// Or from Bun's built-in client:
import { SQL } from "bun";
const sql = new SQL("postgres://[email protected]:5433/srv?sslmode=disable");
const rows = await sql`select 1 as n`;
5 · Branch your data
A branch is an instant copy-on-write fork: it sees the base's data and writes in isolation. Creating one copies no pages.
using preview = db.branch("preview");
preview.exec("INSERT INTO notes VALUES (2, 'branch-only')");
// the base never sees the branch's write, and vice versa