In dit artikel blikt Philip O'Toole terug op de ontwikkeling van gedistribueerd SQLite over een periode van twaalf jaar. Hij start met de creatie van rqlite in 2014, een systeem dat Raft-consensus combineert met SQLite voor fouttolerante opslag.
O'Toole analyseert de verschillende benaderingen die in de loop der jaren zijn ontstaan:
- Consensus (CP-systemen): Zoals rqlite en dqlite, gericht op sterke consistentie via een leader.
- Streaming: Zoals Litestream, dat zich richt op disaster recovery door de WAL naar S3 te streamen zonder een cluster te vereisen.
- Merge (AP-systemen): Zoals cr-sqlite, die gebruikmaakt van CRDT's voor 'local-first' applicaties met uiteindelijke consistentie.
Daarnaast beschrijft hij de verschuiving van open-source tools die men zelf beheert naar commerciële platforms (zoals Turso en Cloudflare D1), waarbij gedistribueerd SQLite is getransformeerd tot een betaalde cloudservice. De auteur concludeert dat de basisvisie — SQLite als storage engine met externe replicatie — correct was en dat rqlite nog steeds een waardevolle, onafhankelijke optie is.
Twaalf jaar gedistribueerd SQLite
In september 2014 publiceerde ik een kort bericht waarin ik rqlite aankondigde. Het idee was simpel: neem SQLite, plaats er een Raft-log voor en repliceer elke schrijfactie naar een cluster, zodat het verlies van een node niet het verlies van data betekende. De broncode werd datzelfde weekend op GitHub geplaatst. Voor zover ik weet, was dat het eerste open-source systeem dat Raft en SQLite combineerde. Niemand anders deed het, en jarenlang heeft niemand anders het geprobeerd.
Tegenwoordig is "gedistribueerd SQLite" een categorie geworden met een dozijn projecten, waarvan er enkele door durfkapitaal zijn gefinancierd en twee zijn overgenomen. Aangezien de mensen die nu over deze categorie schrijven het verhaal meestal laten beginnen rond 2021, dacht ik dat ik de versie die in 2014 begint, op zou moeten schrijven. Ik was er bij het hele proces bij.
2014: rqlite
De behoefte was concreet. Een geclusterd systeem waar ik aan werkte bij jut.io had een kleine hoeveelheid relationele opslag nodig, en de vraag welke node deze moest bevatten, had geen goed antwoord. Het repliceren van SQLite met een consensusprotocol loste dit op. Op het werk kozen we uiteindelijk voor een andere weg, maar ik bleef rqlite bouwen omdat het probleem algemeen was en de oplossing compact.
De eerste versie maakte gebruik van goraft, dezelfde bibliotheek die InfluxDB en etcd destijds gebruikten (rond diezelfde tijd trad ik overigens in dienst bij InfluxDB als core developer). Begin 2016 verving ik dit door de Raft-implementatie van Hashicorp, die rqlite nog steeds gebruikt.
De belangrijkste ontwerpbeslissing die toen werd genomen, is nooit meer veranderd: rqlite is een CP-systeem. Schrijfacties moeten via de leader verlopen, een meerderheid moet de actie bevestigen, en een gepartitioneerde minderheid weigert schrijfacties. Alles wat daarop volgde — de HTTP API, de lees-consistentieniveaus, het maken van snapshots — vloeide voort uit die beslissing.
Voor 2014, en gelijktijdig
Om eerlijk te zijn verdienen twee zaken vermelding. Expensify repliceerde al jaren SQLite binnen hun eigen infrastructuur met een Paxos-stijl protocol; zij brachten dit in 2016 uit als Bedrock. Daarnaast verscheen ActorDB rond dezelfde tijd als rqlite; een Erlang-systeem dat elke "actor" zijn eigen SQLite-database gaf, gerepliceerd door Raft. Geen van beide werd buiten de eigen oorsprong breed geadopteerd, maar ze tonen aan dat het idee in de lucht hing. Wat rqlite deed, was er een standalone, algemeen doel dienend en open-source product van maken dat iedereen kon draaien.
2017: dqlite
Canonical bouwde dqlite om LXD en later MicroK8s van een ingebedde gerepliceerde opslag te voorzien zonder dat etcd gedraaid hoefde te worden. Mark Shuttleworth belde me destijds zelfs op om te kijken of rqlite werkbaar zou kunnen zijn, maar het paste nooit helemaal. dqlite begon in Go en werd later herschreven in C met een eigen Raft-bibliotheek.
Het is het project dat qua intentie het meest lijkt op rqlite. Het belangrijkste verschil zit in de verpakking: dqlite is een bibliotheek die je embedt, rqlite is een server die je draait. De behoefte van Canonical was een database binnen hun producten; mijn behoefte was een database naast het product van wie dan ook.
2021: Litestream en een verandering van aanpak
Ben Johnson (met wie ik bij InfluxDB werkte) bracht begin 2021 Litestream uit. Litestream maakt helemaal geen gebruik van consensus. Het houdt de SQLite WAL (Write-Ahead Log) in de gaten en streamt deze naar S3, wat disaster recovery biedt voor een single-node SQLite-database tegen bijna geen kosten. Ben's argument was dat de meeste applicaties geen cluster nodig hebben; ze gebruiken één machine en hebben een manier nodig om te herstellen als deze uitvalt. Hij had gelijk over een groot aantal applicaties, en de "SQLite is enough"-beweging van de volgende jaren, met bijbehorende blogposts en conferentietalks, is veel aan dat argument te danken.
Litestream en rqlite beantwoorden verschillende vragen:
- Litestream: Wat als de machine sterft?
- rqlite: Wat als de machine sterft en ik niet kan wachten op het herstel?
De eerste vraag komt vaker voor, maar de tweede is de vraag die mensen stellen wanneer ze bij rqlite terechtkomen.
Fly.io nam Ben in 2022 in dienst en lanceerde LiteFS, dat SQLite repliceert op bestandsniveau met leases van Consul. Dit was de eerste poging om gerepliceerd SQLite een platformfunctie te maken in plaats van iets dat je zelf implementeert. In een laatste wending inspireerde Litestream bovendien de aanpak van rqlite v8.0 voor het verwerken van de SQLite WAL.
2022: Forks en extensies
Twee projecten uit 2022 kozen een aanpak die noch rqlite, noch Litestream hanteerden.
cr-sqlite voegde CRDT's toe aan SQLite als extensie, zodat meerdere schrijvers konden divergeren en mergen zonder leader. Dit bevindt zich in de AP-hoek van de ontwerpruimte en is geschikt voor "local-first" applicaties, waar de CP-garanties van rqlite een belemmering zouden zijn.
libSQL forkte SQLite zelf. ChiselStrike, later Turso, wilde zaken binnen de engine veranderen die het SQLite-project (dat geen externe bijdragen accepteert) niet zou wijzigen. Bovenop deze fork bouwden ze een hosted service met replica's aan de "edge". Turso haalde daar durfkapitaal mee op en werd in 2026 overgenomen door Supabase.
Rond diezelfde tijd verscheen SQLite Cloud, dat een hosted SQLite aanbiedt, gerepliceerd met Raft. Dit project ligt het dichtst bij het oorspronkelijke ontwerp van rqlite, maar dan verpakt als een cloudservice.
2022 en verder: De platforms
Cloudflare kondigde in 2022 D1 aan: SQLite als een serverless database binnen hun edge-netwerk, en plaatste later SQLite-opslag binnen Durable Objects. Dit is gerepliceerd SQLite als een beheerd product van een bedrijf dat je niet hoeft uit te leggen hoe het werkt. De service van Turso heeft dezelfde vorm. De categorie is verschoven van "iets dat je draait" naar "iets dat je koopt".
Wat de twaalf jaar laten zien
Ik denk dat dit drie dingen aantoont:
- De kern was juist. SQLite als storage engine, waarbij replicatie aan de buitenkant is toegevoegd, is door ten minste acht teams met verschillende behoeften en protocollen opnieuw uitgevonden. Niemand heeft een reden gevonden om hiermee te stoppen.
- De ontwerpruimte heeft drie hoeken, die in volgorde verschenen:
- Eerst Consensus (rqlite, dqlite): één leader, sterke consistentie, een cluster.
- Daarna Streaming (Litestream): één schrijver, goedkoop herstel, geen cluster.
- Ten slotte Merge (cr-sqlite en delen van de local-first beweging): veel schrijvers, uiteindelijke consistentie (eventual consistency).
Elk van deze is correct voor een andere vraag, en de meeste discussies zijn in feite discussies tussen gebruikers over welke vraag er gesteld wordt.
- Het geld ging naar de platforms. rqlite, dqlite en Litestream zijn open source en gratis. De projecten die kapitaal ophaalden of werden overgenomen, zijn degene die gerepliceerd SQLite hebben omgezet in een service met een rekening. Dat is het gebruikelijke lot van infrastructuur-ideeën, en dat vind ik prima. Maar het is de moeite waard om vast te leggen dat het idee acht jaar lang open source was voordat iemand het verkocht.
rqlite is er nog steeds. Het doet hetzelfde als in 2014, maar een stuk beter. Het blijft de tool waar je naar grijpt als je een fouttolerante relationele database wilt die je zelf kunt draaien, volledig kunt begrijpen en waarvoor je niemand hoeft te betalen. Twaalf jaar later ben ik tevreden met die positie in het verhaal.
Twaalf jaar gedistribueerd SQLite
In september 2014 publiceerde ik een kort bericht waarin ik rqlite aankondigde. Het idee was simpel: neem SQLite, plaats er een Raft-log voor en repliceer elke schrijfactie naar een cluster, zodat het verlies van een node niet het verlies van data betekende. De broncode werd datzelfde weekend op GitHub geplaatst. Voor zover ik weet, was dat het eerste open-source systeem dat Raft en SQLite combineerde. Niemand anders deed het, en jarenlang heeft niemand anders het geprobeerd.
Tegenwoordig is "gedistribueerd SQLite" een categorie geworden met een dozijn projecten, waarvan er enkele door durfkapitaal zijn gefinancierd en twee zijn overgenomen. Aangezien de mensen die nu over deze categorie schrijven het verhaal meestal laten beginnen rond 2021, dacht ik dat ik de versie die in 2014 begint, op zou moeten schrijven. Ik was er bij het hele proces bij.
2014: rqlite
De behoefte was concreet. Een geclusterd systeem waar ik aan werkte bij jut.io had een kleine hoeveelheid relationele opslag nodig, en de vraag welke node deze moest bevatten, had geen goed antwoord. Het repliceren van SQLite met een consensusprotocol loste dit op. Op het werk kozen we uiteindelijk voor een andere weg, maar ik bleef rqlite bouwen omdat het probleem algemeen was en de oplossing compact.
De eerste versie maakte gebruik van goraft, dezelfde bibliotheek die InfluxDB en etcd destijds gebruikten (rond diezelfde tijd trad ik overigens in dienst bij InfluxDB als core developer). Begin 2016 verving ik dit door de Raft-implementatie van Hashicorp, die rqlite nog steeds gebruikt.
De belangrijkste ontwerpbeslissing die toen werd genomen, is nooit meer veranderd: rqlite is een CP-systeem. Schrijfacties moeten via de leader verlopen, een meerderheid moet de actie bevestigen, en een gepartitioneerde minderheid weigert schrijfacties. Alles wat daarop volgde — de HTTP API, de lees-consistentieniveaus, het maken van snapshots — vloeide voort uit die beslissing.
Voor 2014, en gelijktijdig
Om eerlijk te zijn verdienen twee zaken vermelding. Expensify repliceerde al jaren SQLite binnen hun eigen infrastructuur met een Paxos-stijl protocol; zij brachten dit in 2016 uit als Bedrock. Daarnaast verscheen ActorDB rond dezelfde tijd als rqlite; een Erlang-systeem dat elke "actor" zijn eigen SQLite-database gaf, gerepliceerd door Raft. Geen van beide werd buiten de eigen oorsprong breed geadopteerd, maar ze tonen aan dat het idee in de lucht hing. Wat rqlite deed, was er een standalone, algemeen doel dienend en open-source product van maken dat iedereen kon draaien.
2017: dqlite
Canonical bouwde dqlite om LXD en later MicroK8s van een ingebedde gerepliceerde opslag te voorzien zonder dat etcd gedraaid hoefde te worden. Mark Shuttleworth belde me destijds zelfs op om te kijken of rqlite werkbaar zou kunnen zijn, maar het paste nooit helemaal. dqlite begon in Go en werd later herschreven in C met een eigen Raft-bibliotheek.
Het is het project dat qua intentie het meest lijkt op rqlite. Het belangrijkste verschil zit in de verpakking: dqlite is een bibliotheek die je embedt, rqlite is een server die je draait. De behoefte van Canonical was een database binnen hun producten; mijn behoefte was een database naast het product van wie dan ook.
2021: Litestream en een verandering van aanpak
Ben Johnson (met wie ik bij InfluxDB werkte) bracht begin 2021 Litestream uit. Litestream maakt helemaal geen gebruik van consensus. Het houdt de SQLite WAL (Write-Ahead Log) in de gaten en streamt deze naar S3, wat disaster recovery biedt voor een single-node SQLite-database tegen bijna geen kosten. Ben's argument was dat de meeste applicaties geen cluster nodig hebben; ze gebruiken één machine en hebben een manier nodig om te herstellen als deze uitvalt. Hij had gelijk over een groot aantal applicaties, en de "SQLite is enough"-beweging van de volgende jaren, met bijbehorende blogposts en conferentietalks, is veel aan dat argument te danken.
Litestream en rqlite beantwoorden verschillende vragen:
- Litestream: Wat als de machine sterft?
- rqlite: Wat als de machine sterft en ik niet kan wachten op het herstel?
De eerste vraag komt vaker voor, maar de tweede is de vraag die mensen stellen wanneer ze bij rqlite terechtkomen.
Fly.io nam Ben in 2022 in dienst en lanceerde LiteFS, dat SQLite repliceert op bestandsniveau met leases van Consul. Dit was de eerste poging om gerepliceerd SQLite een platformfunctie te maken in plaats van iets dat je zelf implementeert. In een laatste wending inspireerde Litestream bovendien de aanpak van rqlite v8.0 voor het verwerken van de SQLite WAL.
2022: Forks en extensies
Twee projecten uit 2022 kozen een aanpak die noch rqlite, noch Litestream hanteerden.
cr-sqlite voegde CRDT's toe aan SQLite als extensie, zodat meerdere schrijvers konden divergeren en mergen zonder leader. Dit bevindt zich in de AP-hoek van de ontwerpruimte en is geschikt voor "local-first" applicaties, waar de CP-garanties van rqlite een belemmering zouden zijn.
libSQL forkte SQLite zelf. ChiselStrike, later Turso, wilde zaken binnen de engine veranderen die het SQLite-project (dat geen externe bijdragen accepteert) niet zou wijzigen. Bovenop deze fork bouwden ze een hosted service met replica's aan de "edge". Turso haalde daar durfkapitaal mee op en werd in 2026 overgenomen door Supabase.
Rond diezelfde tijd verscheen SQLite Cloud, dat een hosted SQLite aanbiedt, gerepliceerd met Raft. Dit project ligt het dichtst bij het oorspronkelijke ontwerp van rqlite, maar dan verpakt als een cloudservice.
2022 en verder: De platforms
Cloudflare kondigde in 2022 D1 aan: SQLite als een serverless database binnen hun edge-netwerk, en plaatste later SQLite-opslag binnen Durable Objects. Dit is gerepliceerd SQLite als een beheerd product van een bedrijf dat je niet hoeft uit te leggen hoe het werkt. De service van Turso heeft dezelfde vorm. De categorie is verschoven van "iets dat je draait" naar "iets dat je koopt".
Wat de twaalf jaar laten zien
Ik denk dat dit drie dingen aantoont:
- De kern was juist. SQLite als storage engine, waarbij replicatie aan de buitenkant is toegevoegd, is door ten minste acht teams met verschillende behoeften en protocollen opnieuw uitgevonden. Niemand heeft een reden gevonden om hiermee te stoppen.
- De ontwerpruimte heeft drie hoeken, die in volgorde verschenen:
- Eerst Consensus (rqlite, dqlite): één leader, sterke consistentie, een cluster.
- Daarna Streaming (Litestream): één schrijver, goedkoop herstel, geen cluster.
- Ten slotte Merge (cr-sqlite en delen van de local-first beweging): veel schrijvers, uiteindelijke consistentie (eventual consistency).
Elk van deze is correct voor een andere vraag, en de meeste discussies zijn in feite discussies tussen gebruikers over welke vraag er gesteld wordt.
- Het geld ging naar de platforms. rqlite, dqlite en Litestream zijn open source en gratis. De projecten die kapitaal ophaalden of werden overgenomen, zijn degene die gerepliceerd SQLite hebben omgezet in een service met een rekening. Dat is het gebruikelijke lot van infrastructuur-ideeën, en dat vind ik prima. Maar het is de moeite waard om vast te leggen dat het idee acht jaar lang open source was voordat iemand het verkocht.
rqlite is er nog steeds. Het doet hetzelfde als in 2014, maar een stuk beter. Het blijft de tool waar je naar grijpt als je een fouttolerante relationele database wilt die je zelf kunt draaien, volledig kunt begrijpen en waarvoor je niemand hoeft te betalen. Twaalf jaar later ben ik tevreden met die positie in het verhaal.