How Turso's MVCC Improves Write Throughput for Concurrent Transactions
Turso's experimental MVCC (Multi-Version Concurrency Control) replaces the traditional Write-Ahead Log (WAL) lock-based write path with a lock-free, row-level versioning engine that enables multiple writers to execute transactions simultaneously without blocking.
Turso's MVCC implementation fundamentally restructures how SQLite handles concurrent writes by moving from a single-writer page-locking model to a multi-writer row-versioning architecture. Unlike the traditional WAL mode that serializes writers through exclusive locks, MVCC allows connections to begin concurrent transactions immediately, dramatically improving throughput under heavy write loads. This experimental feature in the tursodatabase/turso repository operates through a combination of lock-free data structures and deferred checkpointing.
Eliminating the Single-Writer Bottleneck
Traditional WAL mode requires writers to acquire an exclusive lock on entire database pages before committing changes. This creates a significant bottleneck where only one transaction can write at any given time, forcing other connections to wait or retry.
Turso's MVCC eliminates this contention by implementing row-level versioning instead of page-level locking. When using PRAGMA journal_mode = 'mvcc', the database engine stores modified rows in an in-memory MvStore defined in core/mvcc/database/mod.rs rather than flushing whole pages to disk immediately. This architectural shift allows multiple transactions to create independent versions of the same row without blocking each other.
Lock-Free Data Structures and Snapshot Isolation
The MVCC engine relies on crossbeam_skiplist to manage concurrent access without traditional mutexes. In core/mvcc/mod.rs, the storage layer constructs the MvStore using these lock-free skip-lists (lines 54-55), enabling concurrent insertion and lookup operations without thread contention.
Each transaction receives snapshot isolation based on a begin timestamp taken at BEGIN CONCURRENT. Writers verify only that rows they modify haven't changed since their transaction started, using a lightweight hash-lookup in the version list rather than acquiring global locks. This validation happens entirely in memory until the transaction commits.
The Checkpoint State Machine
While writes remain in memory, durability is maintained through a background checkpoint process. The core/mvcc/database/checkpoint_state_machine.rs file implements a state machine that periodically flushes accumulated row-versions to the B-tree.
During checkpointing, the system acquires only a brief pager lock to write the logical log (.db-log file), then releases it immediately. Because checkpoints run infrequently compared to individual write operations, the average latency for transaction commits remains significantly lower than WAL mode, where each commit may trigger synchronous page flushes.
Enabling MVCC and Running Concurrent Transactions
To activate the MVCC engine, set the journal mode and begin transactions with the concurrent pragma:
-- Enable MVCC mode for the database
PRAGMA journal_mode = 'mvcc';
Once enabled, use BEGIN CONCURRENT to start transactions that can run simultaneously with other writers:
-- Multiple connections can execute this simultaneously without blocking
BEGIN CONCURRENT;
INSERT INTO users (id, name) VALUES (1, 'Alice');
INSERT INTO users (id, name) VALUES (2, 'Bob');
COMMIT;
When using Turso's embedded API, the same pattern applies:
use turso::Connection;
fn concurrent_write(conn: &Connection, id: i64, name: &str) {
conn.execute("BEGIN CONCURRENT").unwrap();
conn.execute(&format!("INSERT INTO users (id, name) VALUES ({}, '{}')", id, name))
.unwrap();
conn.execute("COMMIT").unwrap();
}
The transaction orchestration in core/vdbe/execute.rs handles the BEGIN CONCURRENT logic, ensuring that each connection manages its own version timeline without interfering with other active writers.
Key Performance Optimizations
Turso's MVCC improves write throughput through five specific mechanisms:
-
No exclusive write lock – Writers never wait for a global lock; CPU keeps multiple threads busy processing inserts and updates concurrently.
-
Row-level granularity – Costs are proportional to rows touched, not page sizes. The
MvStoretracks only modified rows rather than rewriting entire pages. -
Lock-free data structures – The
crossbeam_skiplistincore/mvcc/mod.rseliminates mutex contention between writer threads. -
Deferred checkpointing – Writes accumulate in memory while a background checkpoint state machine periodically flushes them to the B-tree, reducing the frequency of disk synchronization.
-
Efficient conflict detection – Write-write conflicts are detected through timestamp comparisons in the version list, avoiding expensive serialization overhead.
Summary
- Turso's MVCC replaces the WAL's single-writer page-locking model with a multi-writer, row-level versioning system.
- The implementation uses lock-free
crossbeam_skipliststructures incore/mvcc/mod.rsto eliminate thread contention. - Transactions use
BEGIN CONCURRENTto achieve snapshot isolation without blocking, with versions stored in theMvStoredefined incore/mvcc/database/mod.rs. - A background checkpoint state machine in
core/mvcc/database/checkpoint_state_machine.rsperiodically flushes the.db-logto the B-tree while holding locks only briefly. - The shift from page-level to row-level granularity significantly reduces write latency and increases throughput for concurrent workloads.
Frequently Asked Questions
How do I enable MVCC in Turso?
Enable MVCC by executing PRAGMA journal_mode = 'mvcc' on your database connection. This switches the storage engine from the default WAL mode to the experimental MVCC engine, allowing subsequent transactions to use BEGIN CONCURRENT for lock-free writes.
What happens when two concurrent transactions modify the same row?
MVCC detects write-write conflicts by comparing timestamps. If two transactions modify the same row, the second commit will fail with a conflict error because the row was modified after the transaction's begin timestamp. This maintains snapshot isolation without requiring readers to block writers.
How does MVCC affect read performance?
Read performance remains efficient because MVCC provides snapshot isolation at the row level. Readers access a consistent view of the database as of their transaction start time without acquiring locks, while the crossbeam_skiplist structure in core/mvcc/mod.rs enables fast version lookups.
Is MVCC suitable for all workloads?
MVCC excels in high-concurrency write scenarios where multiple connections need to commit simultaneously. However, workloads with very large transactions that touch many rows may increase memory pressure in the MvStore before checkpointing occurs, as implemented in core/mvcc/database/checkpoint_state_machine.rs.
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 →