Skip to content
Internals — research note: investigation or findings, not a description of shipped behaviour.
Unverified: This page has not yet been anchored to automated code tests.

VoxDB & Turso Database Audit, Benchmark Estimates, and Comparative Engine Analysis (2026)

VoxDB & Turso Database Audit, Benchmark Estimates, and Comparative Engine Analysis

Section titled “VoxDB & Turso Database Audit, Benchmark Estimates, and Comparative Engine Analysis”

Research status. The codebase findings in §2 cite files you can check. The scorecard (§1) and every performance figure (§3) are unverified estimates: no Vox benchmark run and no per-figure source backs them. Treat them as hypotheses. The measured counterpart is 2026-09-22-voxdb-turso-pooling-benchmark.md, a plan that has not been executed yet.

Vox uses VoxDB (crates/vox-db, aliased as Codex) as its local and canonical embedded database facade. It stores chat transcripts, agent execution history, distributed leases, workflow journals, task queues, telemetry, and package metadata. Today, VoxDB is backed by the turso Rust crate (v0.6.1, evolved from libSQL).

This document audits the operational health and concurrency model of Turso in Vox, verifies performance characteristics against external benchmarks and known engine issues, compares Turso against Standard SQLite, PGlite, and PostgreSQL across their version history, and rates their suitability for Vox’s architecture.

Unverified: the scores and weights below are the author’s judgement, not measurements.

Evaluation Dimension (Weight)Standard SQLite (sqlx / rusqlite pool)Turso / libSQL (turso 0.6.1)PGlite (pglite-rs / WASM)PostgreSQL (Server / Daemon)
Zero-Config Developer Experience (25%)10 / 108.0 / 106.0 / 102.0 / 10
Build Invariants & Toolchain Purity (20%)10 / 103.5 / 10 (clang-sys)3.0 / 10 (C/bison/WASM)10 / 10 (pure driver)
Concurrency & Thread Safety (20%)9.0 / 104.0 / 10 (Misuse / id race)6.0 / 10 (single-proc)10 / 10 (true MVCC)
Startup Time & Latency (15%)9.5 / 108.0 / 104.5 / 10 (20–180ms boot)6.0 / 10 (socket hop)
Resource & Memory Footprint (10%)10 / 107.0 / 104.0 / 10 (25–50MB RSS)3.0 / 10 (daemon RSS)
Replication & Cloud Portability (10%)5.0 / 1010 / 106.5 / 10 (Electric shape)9.0 / 10 (logical rep)
Weighted Total Score (100%)9.15 / 106.45 / 105.08 / 106.05 / 10
Rank for VoxDB Workspace / CLI Store#1 (Recommended)#2 (Current)#4 (Unsuitable)#3 (Hosted Only)

Key Strategic Finding: Vox runs most of its development, testing, and agent workflows in local file mode (.vox/store.db), yet pays the architectural, build-time, and concurrency cost of Turso’s cloud replication design. Turso’s connection-sharing model causes concurrency errors and correctness risks under multi-threaded Tokio. Those errors are documented in code (§2.2).

The proposal (not yet validated) is to move the local embedded engine to an async-safe SQLite pool (sqlx::sqlite::SqlitePool or deadpool-sqlite) and isolate Turso behind an opt-in feature flag (feature = "cloud-sync"). That would remove the bindgen/clang-sys build dependency (§2.3), the last_insert_rowid race and the global mutex bottleneck, and cut binary dependencies.


2. In-Depth Codebase Audit: Turso in VoxDB

Section titled “2. In-Depth Codebase Audit: Turso in VoxDB”
  • Schema Scale: 219 declared tables historically, tracked through monolithic migration milestone BASELINE_VERSION = 93 (crates/vox-db/src/schema/manifest.rs, line 34).
  • Live Storage Census: Per the condensation audit on a representative 5.9MB store.db file:
    • Only 8 tables contain any rows (agent_exec_history=278, agent_events=276, developer_journey_steps=8, schema_version=4, user_preferences=2, conversations=1, developer_journey_definitions=1, history_entries=1).
    • 571 total rows exist across the entire 5.9MB database.
    • Over 95% of the file consists of empty b-tree root and interior pages allocated for 605 schema objects (219 tables + 386 indexes) sharing 1,448 pages of 4,096 bytes each.
  • Worktree Overhead: 19 separate .vox/store.db instances were observed across worktrees (ranging from 1.4MB to 13.3MB each), incurring immediate disk and initialization overhead before any user data is written.

2.2 Concurrency Architecture: The ConcurrentGuard Bottleneck & RowID Race

Section titled “2.2 Concurrency Architecture: The ConcurrentGuard Bottleneck & RowID Race”

In crates/vox-db/src/lib.rs (the GuardedConnection doc comment, around lines 421–470), the codebase documents two critical defects originating from Turso’s connection architecture:

  1. turso::Error::Misuse("concurrent use forbidden"):

    • turso::Connection::clone() does not create an independent connection; it clones an Arc to the same underlying turso_sdk_kit::rsapi::TursoConnection.
    • Turso guards every .step() call with an atomic ConcurrentGuard. When two async tasks on a multi-threaded Tokio runtime execute queries concurrently on cloned handles, the atomic check fails and returns Err(Misuse("concurrent use forbidden")).
    • In the Tauri GUI (vox-gui), this caused routine “Message not saved” toast errors during active chat.
    • The Workaround: Vox implemented GuardedConnection (pub struct GuardedConnection in crates/vox-db/src/lib.rs), forcing all queries across all clones to serialize behind an Arc<tokio::sync::Mutex<()>>. This converts all concurrent reads and writes into sequential operations.
  2. Silent Cross-Task last_insert_rowid() Corruption:

    • As documented under “Known residual gap” in crates/vox-db/src/lib.rs, turso::Connection::last_insert_rowid() is a synchronous, non-blocking read of connection-local state that bypasses ConcurrentGuard.
    • Because GuardedConnection releases the mutex immediately after execute(), a concurrent task on another OS thread can execute an INSERT between task A’s execute() and task A’s last_insert_rowid() read.
    • Impact: Task A silently receives Task B’s row ID. Callsites like chat_ensure_workspace_conversation are exposed to this race condition under high concurrency.

AGENTS.md §Cryptography Policy → Build-toolchain invariant explicitly mandates:

“A clean clone must build with only the pinned Rust toolchain, the platform C compiler, and Node+pnpm. No dependency may add cmake, nasm, Go, perl, or libclang.”

Cargo.lock lists bindgen 0.69.5 as a dependency of turso_sdk_kit 0.6.1, and clang-sys 1.8.1 is present in the graph. The chain, as reported by the original audit:

turso v0.6.1
└── turso_sdk_kit v0.6.1
└── [build-dependencies]
└── bindgen v0.69.5
└── clang-sys v1.8.1 -> requires libclang on host

Unverified: whether a clean build of vox-db really fails on a host without libclang has not been tested. If it does, this violates the invariant above.

  • Batch Execution Restrictions: Turso’s execute_batch uses execute internally and returns an error on any statement that returns rows. Standard SQLite assignment pragmas (PRAGMA journal_mode = WAL) return a row indicating the selected mode and fail if passed to execute_batch. Vox had to build custom pragma_update helpers (crates/vox-db/src/schema/pragmas.rs).
  • Disabled Pragmas: PRAGMA temp_store and PRAGMA mmap_size are deliberately omitted because Turso/libSQL does not support them consistently across local and remote transports.

Unverified. Every figure in this section is an estimate. The original audit attributed the figures collectively to public suites (tursodatabase/turso-sync-benchmark, libSQL issue #1458, ElectricSQL PGlite benchmarks, PostgreSQL pgbench), but it did not tie any single number to a specific run, version, or hardware, and none was reproduced in Vox. Do not cite these numbers as measurements. The pooling/MVCC benchmark plan will produce measured Turso-vs-SQLite figures on Vox’s own workload.

3.1 Latency, Throughput, and Resource Characteristics

Section titled “3.1 Latency, Throughput, and Resource Characteristics”
Performance DimensionStandard SQLite 3.45+ (WAL Mode)Turso / libSQL 0.6.1 (Local File)Turso 0.6.1 (Embedded Cloud Sync)PGlite 0.2/0.3 (WASM in V8/Node)PGlite-rs (Native C Fork)PostgreSQL 16/17 (Localhost Socket)
Point Read Latency ($p_{50}$)8–15 µs40–60 µs45–65 µs250–450 µs80–120 µs350–600 µs
Point Read Latency ($p_{99}$)25–40 µs90–140 µs110–160 µs1,200–1,800 µs200–350 µs1,000–1,500 µs
Point Write Latency ($p_{50}$)60–100 µs180–250 µs35,000–70,000 µs (network roundtrip)600–1,100 µs250–400 µs800–1,200 µs
Batch Write (1,000 rows in tx)3.5–5.0 ms9.0–14.0 ms50.0–85.0 ms35.0–60.0 ms14.0–22.0 ms10.0–18.0 ms
Cold Boot / Startup Time< 1 ms4–8 ms120–250 ms (handshake)50–200 ms (WASM compile/init)15–30 msPre-running daemon required
Single-Threaded Read QPS150k–220k60k–85k55k–75k8k–15k30k–45k15k–25k
Max Concurrent Write TPS~3,500–6,000 (serialized)~2,000–3,500 (serialized)~30–60 (cloud bounded)~800–1,500~2,500–4,00035,000–80,000+ (MVCC)
Idle Memory RSS1–2 MB15–22 MB22–32 MB35–55 MB20–30 MB40–80 MB (client+server)
Compiled Binary Overhead~1.5–2.0 MB~12–15 MB~15–18 MB~25–35 MB~18–24 MB~3.5 MB (driver only)

Note on Latency Differences:

  • Pure in-process C SQLite avoids all asynchronous runtime framing, executing point reads in single-digit microseconds.
  • Turso local mode incurs additional framing overhead from its async state machine, query parameter transformations, and turso_core wrappers.
  • libSQL issue #1458 discusses libSQL’s Rust client being slower than rusqlite in local mode. The claim that WAL-configured throughput lands “within 15–25%” of SQLite is unverified and has not been checked against the issue thread.

  • Best Use Cases:
    • Multi-tenant architectures provisioning isolated databases per user or workspace (e.g. database-per-tenant SaaS).
    • Edge serverless platforms (Cloudflare Workers, Fastly Compute, Vercel Edge) needing low-latency global reads via edge replicas.
    • Mobile or remote IoT applications that require local offline reads but periodically sync to a cloud primary.
  • Worst Use Cases:
    • Embedded local developer CLI tools and desktop apps without cloud sync requirements.
    • Strict hermetic build pipelines prohibiting non-C build dependencies (libclang).
    • Asynchronous multi-threaded applications attempting concurrent access without connection pooling.

4.2 Standard SQLite (with Connection Pooling)

Section titled “4.2 Standard SQLite (with Connection Pooling)”
  • Best Use Cases:
    • Local developer tools (vox), desktop applications (Tauri, Electron), embedded daemons, IDE plugins.
    • Worktree-local isolated storage where instant setup, zero background processes, and sub-millisecond teardown are critical.
    • Deterministic test harnesses running hundreds of isolated test databases in parallel.
  • Worst Use Cases:
    • Horizontally scaled distributed web services requiring multi-node write consensus.
    • Workloads demanding native PostgreSQL specialized types (ltree, hstore, native network types).
  • Best Use Cases:
    • In-browser database applications (WebAssembly) requiring real PostgreSQL SQL dialect compatibility and client-side reactive queries.
    • Integration testing for services targeting PostgreSQL production backends without spinning up Docker or external databases.
    • Client-side applications utilizing pgvector or complex JSONB operators in JavaScript/TypeScript environments.
  • Worst Use Cases:
    • CLI tools where cold boot startup latency (50–200ms) directly degrades interactive execution speed.
    • Resource-constrained systems where running multiple concurrent instances consumes hundreds of megabytes of RSS.
    • Native Rust production systems requiring battle-tested, mature C/Rust bindings.
  • Best Use Cases:
    • Centralized, multi-user web backends and cloud services (vox-server).
    • High-concurrency transactional processing requiring concurrent multi-writer throughput via true MVCC and row-level locks.
    • Complex analytical queries, large-scale graph traversals, and multi-gigabyte vector indexes.
  • Worst Use Cases:
    • Embedded local storage inside standalone CLI binaries.
    • Per-repository or per-worktree databases (causes port conflicts, daemon lifecycle management friction, and credential configuration overhead).

  • 3.35 (2021): Added RETURNING clause on INSERT, UPDATE, and DELETE (eliminating the need for separate last_insert_rowid calls).
  • 3.37 (2021): Introduced STRICT tables for explicit datatype enforcement.
  • 3.38 (2022): Built-in JSON operators -> and ->> matching PostgreSQL syntax.
  • 3.45 (2024): Introduced JSONB, storing JSON in a binary format that accelerates query processing by up to 3x.
  • 3.47+ (2024–2026): CTE memory optimization, defensive corruption prevention, query planner enhancements.
  • 0.1–0.3 (2022–2023): Initial SQLite fork by ChiselStrike. Added the Hrana remote protocol over WebSockets/HTTP.
  • 0.4 (2023–2024): Introduced embedded replicas using page-level WAL replication, allowing local reads with remote cloud sync.
  • 0.5–0.6 (2024–2025): Re-architected into turso_core, turso_sync_engine (logical Protobuf CDC model), and turso_sdk_kit. Renamed crate to turso. Introduced simsimd vector acceleration and the experimental Limbo project (Rust-native SQLite rewrite).
  • 0.6.1 (Current in Vox): Atomic ConcurrentGuard restricts connection concurrency; pulls prost, roaring, and bindgen/clang-sys.
  • 0.1 (Early 2024): Initial public release by ElectricSQL. Packaged PostgreSQL 15/16 into a ~3MB compressed WebAssembly bundle.
  • 0.2 (Late 2024): Extension support (pgvector, pg_trgm, btree_gin), multi-tab worker synchronization, and reactive live queries.
  • 0.3+ (2025–2026): PostgreSQL 16.4+ base; expanded beyond WASM with experimental native single-process C bindings (pglite-rs) and wasmtime bindings (pglite-oxide).
  • 14 (2021): High-connection scalability, JSON subscripting, and LZ4 compression.
  • 15 (2022): Added SQL-standard MERGE, zstd WAL compression, and enhanced sorting performance.
  • 16 (2023): Bidirectional logical replication, CPU SIMD vector acceleration, and pg_stat_io.
  • 17 (2024–2025): Redesigned VACUUM memory management (reducing memory consumption by up to 20x), high-performance bulk loading, streaming I/O, and JSON_TABLE.
  • 18 (2026 Roadmap): Async execution pipeline improvements and tighter vector extension integrations.

6. Concrete Architectural Recommendations for Vox

Section titled “6. Concrete Architectural Recommendations for Vox”

Recommending a raw synchronous rusqlite replacement in an asynchronous Tokio runtime creates executor stalls if blocking C FFI calls run directly on worker threads. The recommended architectural path:

  1. Adopt sqlx::sqlite::SqlitePool for Local VoxDB:

    • Vox already depends on sqlx in crates/vox-sql.
    • sqlx provides a native asynchronous connection pool designed for Tokio.
    • Multiple read connections can execute concurrently under SQLite WAL mode, completely eliminating the GuardedConnection global mutex bottleneck.
    • INSERT ... RETURNING id can be adopted across all mutation callsites, permanently eliminating the last_insert_rowid cross-task race.
    • Compiles cleanly using the platform C compiler without libclang or bindgen.
  2. Isolate Turso Behind feature = "cloud-sync":

    • Retain turso as an optional backend for users who explicitly configure remote database synchronization via VOX_DB_URL and VOX_DB_TOKEN.
    • Standard CLI binaries (vox, vox check) compile without Turso dependencies, cutting clean build times and binary size.
  3. Retain PostgreSQL Exclusively for Hosted Surfaces:

    • Maintain PostgreSQL via vox-sql for vox-server and multi-tenant cloud orchestration.
    • Do not introduce PGlite or embedded Postgres to the CLI; cold startup latency (an unverified 20–180ms estimate) and memory overhead conflict directly with Vox’s performance invariants.
  4. Eliminate Schema Initialization Tax:

    • Transition from monolithic baseline-schema initialization on every fresh database to lazy on-demand table creation (ensure_table) for dormant subsystems (Scientia, Gamify, News Publication).