Limitations of Turso's Experimental MVCC Feature: A Technical Deep Dive
Turso's experimental MVCC implementation currently lacks garbage collection, crash recovery, and true non-blocking checkpoints, making it unsuitable for production workloads.
Turso, the open-source SQLite-compatible database platform maintained by tursodatabase/turso, implements Multi-Version Concurrency Control (MVCC) as an experimental journal mode activated via PRAGMA journal_mode = 'mvcc'. While this feature stores every row change as separate versions in an in-memory skip-list (MvStore) to provide snapshot isolation without blocking readers, several critical architectural constraints remain. Understanding the limitations of Turso's experimental MVCC feature requires examining the source code and documentation to assess whether it fits your use case.
Architecture Overview
Turso's MVCC implementation diverges from the traditional Write-Ahead Log (WAL) mode by maintaining version chains in memory using the MvStore structure defined in core/mvcc/database/mod.rs. When a transaction modifies a row, the system creates a new version in a skip-list and eventually flushes these versions to a logical log file (.db-log) via core/mvcc/persistent_storage/logical_log.rs. The merge logic in core/mvcc/cursor.rs combines these MVCC rows with the underlying B-tree cursor to present consistent snapshots to readers.
Critical Limitations
No Garbage Collection of Old Versions
According to docs/agent-guides/mvcc.md (lines 74-78), the MVCC system accumulates old row versions indefinitely in memory without any garbage collection mechanism. Every update creates a new version in the MvStore skip-list, and these versions persist until the database process terminates. For write-heavy workloads or long-running transactions, this leads to unbounded memory growth that can exhaust available RAM.
No Recovery from Logical Logs
The implementation writes version data to a .db-log file, but as documented in docs/agent-guides/mvcc.md (lines 76-78), the recovery path is not implemented. If the database crashes or restarts, the logical log becomes unusable, and the system cannot reconstruct the MVCC state. This makes the feature unsuitable for any scenario requiring durability across restarts.
Blocking Checkpoints Defeat Non-Blocking Reads
While MVCC promises non-blocking reads, the checkpoint mechanism contradicts this benefit. As noted in docs/agent-guides/mvcc.md (line 81), the checkpoint state-machine acquires a lock that serializes access, blocking all other transactions—including reads—during the checkpoint operation. This effectively eliminates the concurrency advantages typically associated with MVCC architectures.
Memory-Only Version Storage
The system provides no spilling to disk for version data. As stated in docs/agent-guides/mvcc.md (line 82), Turso keeps all versions in RAM, meaning large workloads or datasets with high update rates will exhaust memory resources quickly. This contrasts sharply with production-ready MVCC implementations that page older versions to disk when memory pressure increases.
Index Support Disabled
Many integration tests in the codebase explicitly disable MVCC when indexes are present. Files such as tests/integration/functions/test_cdc.rs contain TODO comments indicating that indexes are not supported under MVCC mode. Queries relying on index lookups will fail or produce incorrect results when the experimental mode is enabled.
Unhandled Data Anomalies
The core MVCC module (core/mvcc/mod.rs, lines 27-30) lists several concurrency control features that remain unimplemented:
- Phantom reads
- Cursor lost updates
- Read/write skew
These gaps in the isolation level implementation mean that complex transactions may observe inconsistent data states that violate snapshot isolation guarantees.
Extension Compatibility Gaps
Full-text search, virtual tables, and other SQLite extensions are not yet MVCC-aware. The test suite in tests/integration/query_processing/ contains numerous TODO comments referencing MVCC compatibility issues, indicating that many advanced SQL features will malfunction or produce undefined behavior when MVCC is active.
Configuration and Usage Examples
Despite these limitations, you can enable MVCC for experimental evaluation:
-- Enable MVCC journal mode (experimental)
PRAGMA journal_mode = 'mvcc';
-- Tune checkpoint frequency (pages written before triggering checkpoint)
PRAGMA mvcc_checkpoint_threshold = 1000;
For Rust integration testing, use the provided test harness:
use turso_macros::test;
/// Test with MVCC enabled
#[turso_macros::test(mvcc)]
fn read_snapshot() {
// Test harness automatically switches to MVCC mode
// Note: Keep write sets modest due to lack of GC
}
When to Use MVCC in Turso
Given the constraints documented in docs/agent-guides/mvcc.md and the source code, MVCC should be restricted to experimental evaluation only. Production workloads must continue using the default WAL journal mode. If you choose to test MVCC, limit write sets to modest sizes, avoid long-running transactions, and ensure you can tolerate complete data loss on restart.
Summary
- No garbage collection: Old versions accumulate indefinitely in memory (
docs/agent-guides/mvcc.md, lines 74-78). - No crash recovery: The
.db-loglogical log cannot be replayed after restart (lines 76-78). - Blocking checkpoints: The checkpoint operation locks the database, serializing all access (line 81).
- Memory-only storage: No disk spilling for version data, risking OOM errors (line 82).
- Limited feature support: Indexes, full-text search, and virtual tables are incompatible or unimplemented.
- Known anomalies: Phantom reads and write skew remain unhandled (
core/mvcc/mod.rs, lines 27-30).
Frequently Asked Questions
What is MVCC in Turso?
MVCC (Multi-Version Concurrency Control) in Turso is an experimental journal mode that stores multiple versions of database rows in an in-memory skip-list (MvStore) to provide snapshot isolation. It can be enabled via PRAGMA journal_mode = 'mvcc' and is intended to allow readers to access consistent snapshots without blocking write transactions, though current implementation limitations prevent this from working as designed in production environments.
Why is Turso's MVCC feature considered experimental?
Turso's MVCC is experimental because it lacks critical production features including garbage collection for old versions, crash recovery from logical logs, and non-blocking checkpoints. Additionally, it does not support indexes, full-text search, or virtual tables, and the implementation has documented TODOs for handling data anomalies like phantom reads and write skew.
Can I use database indexes with Turso MVCC enabled?
No, indexes are not supported when using the experimental MVCC mode. Integration tests in the codebase, such as those in tests/integration/functions/test_cdc.rs, explicitly disable MVCC when indexes are present, and running queries with index scans may produce incorrect results or errors.
How does Turso MVCC handle memory management?
Turso MVCC keeps all row versions in memory with no spilling to disk and no garbage collection. As documented in docs/agent-guides/mvcc.md (lines 74-78, 82), this means memory usage grows unbounded with write volume, making the feature suitable only for small, short-lived experimental workloads rather than production applications.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →