Get Started
Get Started
Add FrankenSQLite to your Rust project and start building with MVCC concurrency and self-healing storage in minutes.
Installation
FrankenSQLite is published on crates.io. Add it to your project with Cargo:
01# Add to your Cargo.toml02cargo add fsqlite03 04# Or add manually:05# [dependencies]06# fsqlite = "0.1"Requirements
- Rust nightly (edition 2024, rust-version 1.85+)
- No system dependencies. Pure Rust, no C compiler needed
- Works on Linux, macOS, and Windows
Quickstart
Open a database, create a table, insert data, and query, all with familiar Rust patterns:
01 fsqlite::Connection;02 fsqlite_error::Result;03 fsqlite_types::value::SqliteValue;04 05 main() -> Result<()> {06 db = Connection::open("app.db")?;07 08 db.execute(09 "CREATE TABLE IF NOT EXISTS users (10 id INTEGER PRIMARY KEY,11 name TEXT NOT NULL,12 email TEXT UNIQUE13 )",14 )?;15 16 db.execute_with_params(17 "INSERT INTO users (name, email) VALUES (?1, ?2)",18 &[19 SqliteValue::Text("Alice".to_owned()),20 SqliteValue::Text("alice@example.com".to_owned()),21 ],22 )?;23 24 stmt = db.prepare("SELECT id, name FROM users WHERE name = ?1")?;25 rows = stmt.query_with_params(26 &[SqliteValue::Text("Alice".to_owned())],27 )?;28 29 row &rows {30 id = row.get(0).expect("id column");31 name = row.get(1).expect("name column");32 println!("Found: {id:?} — {name:?}");33 }34 35 Ok(())36}CLI Shell
FrankenSQLite ships with an interactive CLI shell with syntax highlighting and autocomplete:
01# Install the CLI02cargo install fsqlite-cli03 04# Open or create a database05fsqlite my_database.db06 07# Run queries interactively08fsqlite> CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);09fsqlite> INSERT INTO users VALUES (1, 'Alice');10fsqlite> SELECT * FROM users;11-- 1 | Alice12 13# Output modes14fsqlite> .mode json15fsqlite> SELECT * FROM users;16-- [{"id": 1, "name": "Alice"}]17 18fsqlite> .mode csv19fsqlite> SELECT * FROM users;20-- id,name21-- 1,AliceConfiguration
Configure storage modes,
, and via PRAGMAs:01-- Storage modes: compatibility (default) or native ECS02PRAGMA fsqlite.mode = compatibility; -- Standard .sqlite3 format03PRAGMA fsqlite.mode = native; -- Erasure-Coded Stream format04 05-- Page-level encryption (XChaCha20-Poly1305)06PRAGMA fsqlite.key = 'your-secret-key';07 08-- Transaction observability09PRAGMA fsqlite_txn_stats; -- Lifecycle counters10PRAGMA fsqlite_transactions; -- Active transaction details11PRAGMA fsqlite_txn_advisor; -- Anti-pattern detection12PRAGMA fsqlite_txn_timeline_json; -- Chrome DevTools timeline13 14-- Tune advisor thresholds15PRAGMA fsqlite.txn_advisor_long_txn_ms = 5000;16PRAGMA fsqlite.txn_advisor_large_read_ops = 256;Advanced Examples
These examples showcase FrankenSQLite's unique capabilities beyond standard SQLite.
Concurrent Writers
Four threads writing simultaneously.
eliminates SQLITE_BUSY entirely.01 fsqlite::Connection;02 fsqlite_types::value::SqliteValue;03 std::thread;04 05 main() -> fsqlite_error::Result<()> {06 db = Connection::open("concurrent.db")?;07 db.execute("CREATE TABLE counters (id INTEGER PRIMARY KEY, val INTEGER)")?;08 db.execute("INSERT INTO counters VALUES (1, 0), (2, 0), (3, 0), (4, 0)")?;09 10 handles: Vec<_> = (1..=4).map(|id| {11 thread::spawn( || {12 conn = Connection::open("concurrent.db").unwrap();13 _ 0..1000 {14 conn.execute_with_params(15 "UPDATE counters SET val = val + 1 WHERE id = ?1",16 &[SqliteValue::Integer(id)],17 ).unwrap();18 }19 })20 }).collect();21 22 h handles { h.join().unwrap(); }23 // Each counter is exactly 1000 — no SQLITE_BUSY, no lost updates.24 Ok(())25}Time-Travel Queries
inspect the database at any past point using commit sequence numbers.01 fsqlite::Connection;02 03 main() -> fsqlite_error::Result<()> {04 db = Connection::open("history.db")?;05 db.execute("CREATE TABLE prices (item TEXT, price REAL)")?;06 db.execute("INSERT INTO prices VALUES ('widget', 9.99)")?;07 08 // Record the commit sequence number09 csn_before = db.query_scalar("SELECT fsqlite_current_csn()")?;10 11 db.execute("UPDATE prices SET price = 14.99 WHERE item = 'widget'")?;12 13 // Query the current state14 current = db.prepare("SELECT price FROM prices WHERE item = 'widget'")?;15 // => 14.9916 17 // Time-travel: query the database as it was before the update18 historical = db.prepare(19 "SELECT price FROM prices FOR SYSTEM_TIME AS OF ?1 WHERE item = 'widget'",20 )?;21 rows = historical.query_with_params(&[csn_before])?;22 // => 9.99 — the price before the update23 24 Ok(())25}ECS Mode + Encryption
Native
storage with and configurable repair ratios.01 fsqlite::Connection;02 fsqlite_types::value::SqliteValue;03 04 main() -> fsqlite_error::Result<()> {05 db = Connection::open("secure.db")?;06 07 // Switch to native ECS format for maximum durability08 db.execute("PRAGMA fsqlite.mode = native")?;09 10 // Enable page-level encryption (XChaCha20-Poly1305 + Argon2id KDF)11 db.execute("PRAGMA fsqlite.key = 'hunter2-but-stronger'")?;12 13 // Configure RaptorQ repair symbol ratio (default: 0.1 = 10% overhead)14 db.execute("PRAGMA fsqlite.repair_ratio = 0.2")?; // 20% for extra safety15 16 // Business as usual — the API is identical17 db.execute("CREATE TABLE secrets (id INTEGER PRIMARY KEY, data BLOB)")?;18 db.execute_with_params(19 "INSERT INTO secrets (data) VALUES (?1)",20 &[SqliteValue::Blob(b"classified".to_vec())],21 )?;22 23 // Every page is encrypted at rest + protected by RaptorQ repair symbols.24 // Even if the disk suffers corruption, data is recoverable.25 Ok(())26}FAQ
Why FrankenSQLite?
SQLite is single-writer, has no self-healing, and is written in C. FrankenSQLite is a clean-room Rust reimplementation that adds
(concurrent writers), (self-healing pages), and (compiler-enforced memory safety). Same SQL dialect, fundamentally different engine.Is it a drop-in replacement for SQLite?
It reads and writes standard .sqlite3 files and supports the full SQL dialect. The Rust API is different from the C API, but migration is straightforward.
How does MVCC work?
FrankenSQLite maintains multiple versions of each page. Readers see a consistent snapshot while writers operate independently, resolving collisions with
. No more SQLITE_BUSY errors.What is RaptorQ self-healing?
fountain codes mathematically generate redundant repair symbols. If bit rot or disk corruption occurs, the database can automatically reconstruct damaged pages.What are the storage modes?
FrankenSQLite supports two storage modes. Compatibility mode reads and writes standard .sqlite3 files for direct migration from C SQLite. Native mode uses the
format with append-only commits, -protected pages, and built-in . Switch between them withPRAGMA fsqlite.mode.What is the ECS format?
is FrankenSQLite's native storage format. It uses BLAKE3 hashes, append-only commits, and repair symbols for continuous parity. The means normal reads are zero-copy, and decoding only happens when corruption is detected.How does the safe merge ladder work?
The
tries four strategies in order: (1) intent replay (re-applying the logical operation), (2) merge (canonical reordering of independent writes), (3) merge (combining byte-level diffs), and (4) abort as a last resort. Most real-world “conflicts” are safely merged without aborting.What are time-travel queries?
let you inspect the database at any past point usingFOR SYSTEM_TIME AS OF with a commit sequence number or timestamp. The version chain holds full history, meaning no snapshots, forks, or replicas are needed.Does FrankenSQLite use any unsafe Rust?
No. The entire 26-crate workspace enforces
via#![forbid(unsafe_code)]. This structurally prevents buffer overflows, use-after-free, double-free, and data races. The adds further compile-time safety by preventing accidental mixing of PageNumber with TxnId.How does encryption work?
Every 4KB page is encrypted independently with
. The page number is bound as authenticated data, so moving ciphertext between page slots is detected and rejected. Keys use a , so changing the passphrase rewraps a single 32-byte key instead of re-encrypting every page.What are learned indexes and database cracking?
fit a piecewise linear model to the key distribution, replacing B-tree traversal with arithmetic prediction plus a bounded scan. partitions column data in-place as queries arrive, so the index builds itself from the workload. Together they provide adaptive, zero-admin indexing.How does the page cache work?
FrankenSQLite uses an
page cache that self-tunes the balance between recency and frequency. On top of that, a (HOT/COOLING/COLD) prevents full-table scans from thrashing the buffer pool. Hot B-tree pages use to bypass the cache lookup entirely.Is it production ready?
FrankenSQLite is under active development. The architecture is solid but it should be evaluated carefully for production workloads. Contributions welcome!