Marmot: Multi-writer distributed SQLite based on NATS
github.com
github.com
- LiteSync directly competes with Marmot and supports DDL sync, but is closed source commercial (similar to SQLite EE): https://litesync.io
- dqlite is Canonical's distributed SQLite that depends on c-raft and kernel-level async I/O: https://dqlite.io
- cr-sqlite is a Rust-based loadable extension that adds CRDT changeset generation and reconciliation to SQLite: https://github.com/vlcn-io/cr-sqlite
Slightly related but not really (no multi writer, no C-level SQLite API or other restrictions):
- comdb2 (Bloombergs multi-homed RDBMS using SQLite as the frontend)
- rqlite: RDBMS with HTTP API and SQLite as the storage engine, used for replication and strong consistency (does not scale writes)
- litestream/LiteFS: disaster recovery replication
- liteserver: active read-only replication (predecessor of LiteSync)
https://medium.com/chiselstrike/introducing-embedded-replica...
https://use.expensify.com/blog/scaling-sqlite-to-4m-qps-on-a...
That plus a globally incrementing version number is what I want…
- Sidecar! I would avoid any kind of in process library at any cost. Call me biased but I don't trust someone's code in my process space causing it to crash.
- No master - each node should be able to make progress on its own, if these processes go down your own process will keep functioning. They will converge once everything is back.
- Easy to start, yet hard to master - You can get up and running pretty quickly, but make no mistake this tool is not for rookie who doesn't understand how incremental primary keys are bad, and how to they can keep things conflict free.
I am far from getting everything I need in there, and again my philosophy might evolve over time as well. Talking to people on Discord has helped me think through use-cases a lot, so keep the good feedback coming. Would love to answer any questions people might have here.
This is a neat proof of concept and I encourage experimentation. But, if you're developing something, please just use postgres, and don't try to cobble things together with something like this.
Edit: already seeing the downvotes. Yes... classic HN... anything that goes against plain old sanity is punished.
I think the important thing is to encourage devs to understand transactions in the first place.
Won’t downvote you for giving pragmatic advice, but I appreciate projects like this that slap together disparate technologies for an interesting goal, even if it isn’t the best choice for your usual Fortune 500 company.
That's exactly why I said: "This is a neat proof of concept and I encourage experimentation."
Some companies only have juniors. 28 years ago, I was the junior at my company, and the first/only engineer.
Let's also be real here, most applications don't need distributed Postgres either and those that do, will have senior engineers on staff.
Wild thought, this is not my experience at all. I don't even understand how you can come to the conclusion.
I posit that if you're at that scale, you're figuring out how to get distributed postgres to work and not messing with things like Marmot.
If you absolutely need to distribute data, it means you're working at a scale where things are already complex.
Using SQLite for that will not simplify your life, it will just make it harder to tackle the complexity.
Unless you are extremely careful, eventually consistent writes are almost guaranteed to produce behaviors that are hard / impossible to anticipate during development. And a PITA to debug.
and
> This means there is NO serializability guarantee of a transaction spanning multiple tables. This is a design choice, in order to avoid any sort of global locking, and performance.
But since the serialization happens at per row level, does this also mean no serializability guarantee of a transaction within a table too, not only spanning multiple tables?
If I had any technical issues (i.e. questions, optimizations etc) I always asked the developer maxpert and he gave me in-depth answers that helped me personally a lot.
In my case I have much love for Marmot and hopefully it grows and helps a bigger community
However, my main goal for Marmot was to decrease the latency of my website by putting the db as close as I can to the end user
It's about +5M requests per day or ~2B per year. That's on the lower end! The higher end is ~20B requests per year!
I think using distributed SQL for that kind of scale may not be a wise choice, but that's my opinion...
To me the multi-writer "collaborative" use case is super powerful but also has a lot of challenges. I personally would see a lot of value in a solution for eventually consistent read-replicas that are available for end-client (WASM or mobile native) replication but still funnel updates through traditional APIs with store-and-forward for the offline case.
Is anybody aware of an open-source project pursuing that goal that maybe I haven't come across?
If I have a table with a string primary key and I insert a row in one node with ID "hello" and do the same thing (but with different column data) on another node, what happens?
"the last writer will always win. This means there is NO serializability guarantee of a transaction spanning multiple tables. This is a design choice, in order to avoid any sort of global locking, and performance."
So it sounds like in your example, whichever node writes last with a given primary key will be the data you'll end up with.
Within a single table they have tx serializability, just not with multiple tables
A great point, but from the readme in the Marmot repo:
> It does not require any changes to your existing SQLite application logic for reading/writing.
I suspect you’re probably still right, but that’s not what the author claims.
The question remains - how does Marmot enforce a uniqueness constraint? If you don’t like the product example, fine, but it is easy to think of others. It would be unfortunate if marmot is incapable of supporting uniqueness.
Nobody pushes an application out just once.