Quick_Start

Get Started

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:

terminal
01# Add to your Cargo.toml02cargo add fsqlite03 04# Or add manually:05# [dependencies]06# fsqlite = "0.1"
Syntax_Validation_Active
UTF-8_ENCODED

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:

examples/quickstart.rs
01
use
fsqlite::Connection;
02
use
fsqlite_error::Result;
03
use
fsqlite_types::value::SqliteValue;
04 05
fn
main() -> Result<()> {
06
let
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
let
stmt = db.prepare("SELECT id, name FROM users WHERE name = ?1")?;
25
let
rows = stmt.query_with_params(
26 &[SqliteValue::Text("Alice".to_owned())],27 )?;28 29
for
row
in
&rows {
30
let
id = row.get(0).expect("id column");
31
let
name = row.get(1).expect("name column");
32 println!("Found: {id:?} — {name:?}");33 }34 35 Ok(())36}
Syntax_Validation_Active
UTF-8_ENCODED

CLI Shell

FrankenSQLite ships with an interactive CLI shell with syntax highlighting and autocomplete:

terminal
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,Alice
Syntax_Validation_Active
UTF-8_ENCODED

Configuration

Configure storage modes,

, and
via PRAGMAs:

terminal
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;
Syntax_Validation_Active
UTF-8_ENCODED

Advanced Examples

These examples showcase FrankenSQLite's unique capabilities beyond standard SQLite.

Concurrent Writers

Four threads writing simultaneously.

eliminates SQLITE_BUSY entirely.

examples/concurrent_writers.rs
01
use
fsqlite::Connection;
02
use
fsqlite_types::value::SqliteValue;
03
use
std::thread;
04 05
fn
main() -> fsqlite_error::Result<()> {
06
let
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
let
handles: Vec<_> = (1..=4).map(|id| {
11 thread::spawn(
move
|| {
12
let
conn = Connection::open("concurrent.db").unwrap();
13
for
_
in
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
for
h
in
handles { h.join().unwrap(); }
23 // Each counter is exactly 1000 — no SQLITE_BUSY, no lost updates.24 Ok(())25}
Syntax_Validation_Active
UTF-8_ENCODED

Time-Travel Queries

inspect the database at any past point using commit sequence numbers.

examples/time_travel.rs
01
use
fsqlite::Connection;
02 03
fn
main() -> fsqlite_error::Result<()> {
04
let
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
let
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
let
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
let
historical = db.prepare(
19 "SELECT price FROM prices FOR SYSTEM_TIME AS OF ?1 WHERE item = 'widget'",20 )?;21
let
rows = historical.query_with_params(&[csn_before])?;
22 // => 9.99 — the price before the update23 24 Ok(())25}
Syntax_Validation_Active
UTF-8_ENCODED

ECS Mode + Encryption

Native

storage with
and configurable
repair ratios.

examples/ecs_encryption.rs
01
use
fsqlite::Connection;
02
use
fsqlite_types::value::SqliteValue;
03 04
fn
main() -> fsqlite_error::Result<()> {
05
let
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}
Syntax_Validation_Active
UTF-8_ENCODED

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 with PRAGMA 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 using FOR 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!