SQLite is the world's most widely used database. It runs everywhere, from smartphones and browsers to embedded devices and applications of every imaginable kind. With trillions of installations, it is arguably one of the most successful pieces of software ever written.
Yet, whenever I talk about SQLite, there is one question that inevitably comes up:
“But what about the fact that SQLite only allows one writer at a time?”
And it’s a fair question.
SQLite has always been incredibly reliable, fast, and simple. But its single-writer architecture has remained one of its most frustrating limitations, especially for applications that need to handle many concurrent operations.
Of course, developers have found ways to work around this limitation. WAL mode, busy timeouts, transaction batching, write queues, and other techniques can help mitigate the problem. But none of them fundamentally changes the fact that only one writer can hold the write lock at a time.
Even the SQLite core team experimented with addressing this through the BEGIN CONCURRENT branch, which was never merged into the main SQLite codebase.
More recently, our friends at Turso approached the problem from a different direction, implementing an MVCC engine in their own SQLite rewrite.
But what if we could solve this problem without rewriting SQLite, without modifying a single line of its source code, while supporting multiple processes (not just threads), and without sacrificing compatibility with existing databases?
The tweet that changed everything
I have been thinking about this problem for years.
I knew it was important, and I had explored several possible approaches, but I have to admit that I never found a sufficiently compelling reason to dedicate the time and resources required to solve it properly.
Until one day, I came across this tweet from Peter Steinberger:
The biggest design mistake I made when we moved OC to sqlite: using sync db access. When it was just an agent that reports to you on Slack or iMessage this was fine; now that one agent might do 50 sessions in parallel and the whole team works on it, it is limiting.
That was the moment something clicked.
AI agents are changing the way we build and use software. We are moving from applications where a single user performs a sequence of operations to systems where dozens, hundreds, or potentially thousands of agents operate concurrently.
And SQLite, with its simplicity, portability, and zero-configuration architecture, is an almost perfect database for this new world.
Except for that one limitation.
That was the moment I decided we had to fix it.
Four requirements. One ambitious goal.
From the beginning, I wanted to impose a few strict requirements on ourselves:
Existing SQLite databases must remain compatible. No new database format, no migrations, no special schema.
SQLite itself must remain untouched. No forks, patches, or custom SQLite builds.
Support both multithreading and multiprocessing. Multiple threads, multiple processes, and multiple agents should be able to write to the same database.
It must be as transparent as possible. Developers and AI agents should continue using familiar SQLite APIs and SQL, without learning a completely new database system.
We explored several different architectures and implementations. Some approaches looked promising but introduced unacceptable trade-offs. Others worked well in specific scenarios but couldn’t satisfy all four requirements. Eventually, we found an approach that we believe changes what is possible with SQLite.
Introducing sqlite-multiwriter
Today, I’m incredibly excited to introduce sqlite-multiwriter.
An open-source project that enables multiple concurrent writers on a single SQLite database, without modifying SQLite itself.
The key is a custom SQLite Virtual File System (VFS).
Instead of forcing every writer to compete for the same database write lock, sqlite-multiwriter allows writers to work independently on their own snapshots, using private write-ahead logs.
writer 1 --> private WAL --+
writer 2 --> private WAL --+--> check and publish --> commit log --> database file
writer 3 --> private WAL --+ (first committer wins) (compaction)When a transaction commits, the engine validates its changes against other committed transactions, safely publishes compatible changes, and maintains durable storage.
We also implemented an optional rebase mechanism that can resolve certain page-level conflicts when transactions modify different rows on the same page.
The result is a database that remains SQLite, with the same SQL, the same APIs, and an ordinary SQLite database file, but with a completely different approach to concurrent writes.
There are still genuine conflicts that require transaction retries, and the engine has documented limitations. But independent writers no longer need to be serialized behind a single write lock. And the performance improvements are remarkable.
The numbers speak for themselves
We benchmarked sqlite-multiwriter against standard SQLite in WAL mode, using full synchronous durability.
With 16 threads writing to the same database:
+-------------------------+---------+--------------------+
| Metric | SQLite | sqlite-multiwriter |
+-------------------------+---------+--------------------+
| Transactions per second | 8,630 | 49,277 |
| Throughput improvement | - | 5.7x |
| p99.9 latency | 157 ms | 2.08 ms |
+-------------------------+---------+--------------------+With 16 processes writing to the same database
+-------------------------+---------+--------------------+
| Metric | SQLite | sqlite-multiwriter |
+-------------------------+---------+--------------------+
| Transactions per second | 8,636 | 25,987 |
| Throughput improvement | - | 3.0x |
| p99.9 latency | 233 ms | 1.54 ms |
+-------------------------+---------+--------------------+These results are for workloads where writers insert their own rows. Other workloads, especially those involving genuine conflicts on the same rows, will produce different results.
But here’s what I find particularly exciting: it isn’t just about throughput.
It’s also about eliminating much of the unpredictable waiting that makes concurrent SQLite workloads difficult to manage.
For AI agents, where many independent sessions might need to update the same database simultaneously, reducing tail latency can make an enormous difference.
You can find the complete benchmarks, methodology, implementation details, and instructions to reproduce the results in the GitHub repository.
Open source, because this belongs to everyone
We decided to release sqlite-multiwriter as a fully open-source project under the permissive Apache 2.0 license.
SQLite has given an extraordinary amount to the software community, and we believe improvements like this should be accessible to everyone.
This is also just the beginning.
There is still work to do: more testing, more workloads, more platforms, more optimizations, and probably edge cases we haven’t encountered yet.
And that’s exactly why we’re making it open source.
We would love to see developers experiment with it, challenge our assumptions, reproduce the benchmarks, report problems, propose improvements, and contribute code.
We especially encourage people building AI agents, developer tools, local-first applications, and systems with high concurrency requirements to give it a try.
Clone the repository. Run the tests. Break things. Tell us what doesn’t work. Help us make it better.
Explore sqlite-multiwriter on GitHub →
A final thought
What excites me most about this project isn’t the benchmark numbers.
It’s the possibility of removing a limitation that developers have accepted for decades, while preserving everything that makes SQLite so special.
And I genuinely believe we’re only beginning to understand how important SQLite will become in a world where software is increasingly built and operated by autonomous agents.
SQLite has always been everywhere. Now, we want it to be ready for everyone writing at once.
