SQLite distribuído: 5 mitos testados após 12 anos
Após doze anos de SQLite distribuído (Raft, Litestream, Turso, D1), testamos cinco crenças sobre consistência, replicação e quando usar Postgres.

O SQLite distribuído passou de projeto de fim de semana de uma pessoa para uma categoria de produto financiada por investidores sem que a maioria dos engenheiros percebesse a década no meio. Em setembro de 2014, Philip O'Toole colocou um log Raft na frente do SQLite, replicou cada escrita por um cluster e publicou o código no GitHub como rqlite. Doze anos depois existe um ecossistema inteiro (dqlite, Litestream, LiteFS, cr-sqlite, libSQL/Turso, Cloudflare D1) e grande parte do que as pessoas acreditam sobre ele está errada de formas interessantes.
Eu já rodei bancos de dados em cluster em produção e limpei a bagunça dos modos de falha deles, então deixa eu poupar você de algumas dores de cabeça: as discussões sobre SQLite distribuído quase nunca são sobre SQLite. São sobre qual pergunta você está realmente fazendo: e se a máquina morrer, e se ela morrer e eu não puder esperar, ou e se não existir máquina nenhuma. Aqui estão cinco mitos, testados contra doze anos de história.
Mito 1: SQLite distribuído é uma ideia recente
A onda atual de textos sobre SQLite replicado começa por volta de 2021, quando o Litestream e o movimento “SQLite is enough” ficaram barulhentos, e o Turso e o Cloudflare D1 chegaram com financiamento e posts de lançamento. Assim se consolidou a crença de que alguém esperto tinha percebido recentemente que o SQLite podia ser replicado. Na verdade, o primeiro sistema Raft sobre SQLite foi lançado em 2014, e nem foi a primeira replicação de SQLite: a Expensify já fazia isso internamente com um protocolo do tipo Paxos havia anos antes de liberar o Bedrock em 2016, e o ActorDB deu a cada ator Erlang seu próprio banco SQLite replicado com Raft mais ou menos na mesma época.
Por que isso importa além dos créditos? Porque um design que sobrevive doze anos de reinvenção independente diz alguma coisa. Pelo menos oito equipes diferentes, com necessidades e protocolos diferentes, olharam para o problema e chegaram à mesma arquitetura: SQLite como motor de armazenamento, com a replicação acoplada por fora. Ninguém encontrou motivo para parar de fazer isso. Quando você vê esse padrão, uma reimplementação convergente ao longo de uma década, está diante de uma ideia realmente boa, e não de um ciclo de hype. Compare com categorias que surgem e somem; esta foi acumulando.
Também importa porque as decisões antigas de design ainda sustentam a estrutura. O rqlite escolheu ser um sistema CP em 2014 (as escritas passam pelo líder, uma maioria precisa confirmar, e uma minoria particionada recusa escritas) e nunca mudou de ideia. Essa única escolha determinou a API HTTP, os níveis de consistência de leitura e o comportamento de snapshots. Times que tratam consistência como um botão de configuração a ser decidido depois geralmente se arrependem; a distância entre a especificação que você imaginou e a que você implementou é exatamente onde os bugs distribuídos se proliferam.
Mito 2: Raft sobre SQLite te dá um Postgres distribuído barato
Este é o mito mais caro da lista. A proposta soa tentadora: pegue o banco de dados mais implantado do mundo, adicione consenso e evite o peso operacional de um sistema cliente-servidor. O que você realmente recebe é um banco de escrita única em que cada escrita paga um round trip de rede até a maioria dos nós, e em que a superfície SQL do SQLite (sem stored procedures, sistema de tipos enxuto, primitivas de concorrência limitadas) continua sendo a superfície SQL do SQLite.
O caminho de escrita é o custo honesto. Um commit local no SQLite são alguns fsyncs. Um commit replicado via Raft é: o líder anexa ao seu log, envia a entrada aos seguidores, espera a maioria persistir, aplica no SQLite e só então responde. Numa LAN saudável isso dá uns um ou dois milissegundos em vez de dezenas de microssegundos. Entre regiões, é a velocidade da luz mais o disco. Para cargas com muitas leituras e taxa de escrita moderada, como stores de configuração, metadados de service discovery e pequenos control planes, tudo bem, e é exatamente o nicho para o qual o rqlite foi criado (a origem dele é um sistema em cluster que precisava de um pouco de armazenamento relacional, sem uma boa resposta sobre qual nó deveria guardá-lo). Para um workload OLTP intenso, é a ferramenta errada.
E depois existe a realidade operacional que ninguém coloca no README: a eleição de líder é um modo de falha que agora é seu. Split-brain é evitado por votação por maioria, sim, mas isso significa que um cluster de três nós que perde dois nós recusa todas as escritas. Você trocou “o banco caiu porque o servidor morreu” por “o banco caiu porque o quórum morreu”, e a segunda situação é mais difícil de explicar para o plantão às 3 da manhã. Se você ainda não pensou em testes no estilo Jepsen para o sistema escolhido, deveria: um comentarista do Hacker News perguntou, de forma certeira, se o rqlite já passou por testes Jepsen, porque sistemas que não passaram costumam ter surpresas escondidas. Enquanto isso, um engenheiro experiente na mesma discussão observou que, com as ferramentas atuais, rodar um Postgres de verdade ficou fácil o bastante para que “use simplesmente um servidor de banco” seja, de novo, um padrão legítimo. Ele não está errado.

Mito 3: Replicação significa consenso
Se existe uma lição que a história de doze anos realmente entrega, é esta: “SQLite replicado” não é um design único, e sim três cantos de um espaço de design, e eles surgiram numa ordem reveladora. Confundi-los é como times acabam rodando um cluster Raft para resolver um problema de backup.
- Consenso (CP). rqlite, dqlite. Um líder, consistência forte, um cluster de verdade. Responde: “e se a máquina morrer e eu não puder esperar para restaurar?” Custo: latência de escrita e operações de quórum.
- Streaming (escritor único). Litestream, depois LiteFS. Sem consenso nenhum: o WAL do SQLite é transmitido para object storage, oferecendo recuperação de desastres quase contínua para um único nó. Responde: “e se a máquina morrer?” Custo: uma pequena janela de possível perda de dados e tempo de restauração medido em segundos ou minutos.
- Merge (AP). cr-sqlite e o movimento local-first. CRDTs como extensão do SQLite, com muitos escritores divergindo e fazendo merge sem líder. Responde: “e se não existir máquina central nenhuma?” Custo: consistência eventual e semânticas de merge que você precisa projetar.
O argumento do Ben Johnson para o Litestream merece respeito porque estava certo sobre a maioria das aplicações: elas rodam em uma máquina e precisam de um jeito de se recuperar quando ela morre, não de um cluster. A primeira pergunta, “e se a máquina morrer”, é muito mais comum que a segunda, “e eu não posso esperar para restaurar”. Já vi times implantarem um cluster Raft de três nós para proteger um banco cujo requisito de RTO era “algum momento antes do almoço”. Isso não é engenharia de confiabilidade, é cargo cult. Num fechamento bonito do ciclo, a abordagem de streaming de WAL do Litestream acabou inspirando como o próprio rqlite lida com o WAL na v8: o canto de streaming alimentou o canto de consenso.
Então, antes de escolher uma ferramenta, escreva a pergunta. Literalmente. “Quando o nó X morrer, precisamos que as escritas voltem em N segundos, e aceitamos perder os últimos M segundos de dados confirmados.” Se M for de alguns segundos e N for de um minuto, Litestream para S3 é a sua resposta e ele nunca vai te acordar por causa de quórum. Se M for zero e N for de segundos, você está em território de consenso e vai pagar por isso em cada escrita. É a mesma disciplina de qualquer modelagem de ameaças: nomeie a falha antes de comprar a defesa, do mesmo jeito que você abordaria sistemas que resistem a catástrofes, decidindo de antemão qual catástrofe está resistindo.
Mito 4: “SQLite na borda” gerenciado elimina os trade-offs
O dinheiro dessa categoria foi para as plataformas: o Turso captou investimento de risco e foi adquirido pela Supabase; a Cloudflare lançou o D1 dentro da sua rede de borda. A proposta é que alguém agora cuida das partes distribuídas difíceis. Às vezes é verdade. Às vezes é marketing, e o segredo sujo vaza: um desenvolvedor da Cloudflare admitiu publicamente que o D1 é essencialmente um wrapper em torno de um Durable Object singleton que expõe o seu banco SQLite, e que você frequentemente se sai melhor usando o armazenamento de Durable Objects diretamente. Isso não é um banco distribuído no sentido de consenso; é um único arquivo SQLite com uma plataforma em volta. Usuários que rodam o D1 em produção relatam confiabilidade à altura.
Nada disso significa que as opções gerenciadas são ruins. Significa que os trade-offs não desapareceram: foram para trás de uma API onde você não consegue inspecioná-los. Quando você roda o rqlite por conta própria, sabe exatamente o que CP significa: três nós, um líder, confirmação da maioria, minoria particionada recusa escritas. Quando você compra “SQLite na borda”, precisa fazer as mesmas perguntas a uma caixa-preta: onde está o escritor, o que acontece em uma partição, qual é a sua janela real de durabilidade? Se a resposta do fornecedor for vaga, a sua revisão de incidente também será.
Replicação como serviço não elimina a pergunta sobre consistência. Ela só move a resposta para a infraestrutura de outra pessoa, onde você não consegue auditá-la.
O padrão histórico vale a pena ser internalizado: os sistemas open source (rqlite, dqlite, Litestream) trabalharam a ideia por oito anos antes de alguém vendê-la, e o capital foi para quem transformou a ideia em serviço com fatura. Esse é o destino usual da infraestrutura. Comprar muitas vezes é a decisão certa, mas compre sabendo bem qual dos três cantos você está realmente levando.

Mito 5: Consistência forte é um upgrade grátis em relação a backups
As pessoas enquadram a escolha como backups (fracos, baratos) versus consenso (fortes, caros, mas estritamente melhores). Não é verdade. Consistência forte via Raft é outro produto, não uma versão melhor do mesmo produto, e impõe impostos contínuos que backups nunca impõem.
Imposto um: throughput. Um praticante que usou os dois observou que o rqlite oferece garantias de “armazenado em mais de um lugar”, mas é bem mais lento que um banco de um nó só. É o round trip do consenso, e ele nunca desaparece. Imposto dois: semântica sutil. Se você replica enviando instruções SQL, herda problemas de determinismo: funções como random() ou datetime('now') podem divergir entre os nós, a menos que a camada as reescreva, e é por isso que algumas implementações suportam apenas um subconjunto do SQL do SQLite. Replicar no nível do WAL evita isso, mas acopla você ao formato em disco e ao layout de páginas do SQLite. Não existe posicionamento de camada sem algum compromisso. Imposto três: transações distribuídas são genuinamente difíceis. Um engenheiro descreveu a evolução de um design em que cada instrução de uma transação era um comando Raft separado (mais ou menos correto, mas lento) para outro em que o nó iniciador executa a transação inteira localmente, faz rollback e envia um único comando de commit com o lote inteiro. É o tipo de lição duramente conquistada que só se aprende operando esses sistemas.
Aqui vai uma ilustração mínima da diferença no caminho de escrita, usando a API HTTP do rqlite:
# Local SQLite: one process, one fsync, microseconds.
sqlite3 app.db "INSERT INTO kv VALUES ('flag', 'on')"
# rqlite: this HTTP call hides a Raft round trip —
# leader log append, replication to a majority, then apply.
curl -XPOST 'localhost:4001/db/execute?pretty' \
-H 'Content-Type: application/json' \
-d '["INSERT INTO kv VALUES (?, ?)", "flag", "on"]'
# The guarantee changed: the write now survives the loss
# of any single node. So did the latency budget.
E repare no que você não ganhou: escalabilidade de leitura. O Raft replica o log para que os seguidores possam assumir; ele não faz os seguidores servirem leituras fortemente consistentes por padrão (o rqlite oferece níveis de consistência de leitura justamente porque isso é um trade-off). Se você veio pelo “distribuído” esperando mais capacidade de leitura, você queria réplicas de leitura, não consenso.
O que doze anos de Raft sobre SQLite realmente ensinam
A história da categoria é uma evidência incomumente limpa de como ideias de infraestrutura amadurecem. Primeiro, alguém constrói a solução principiada para uma necessidade concreta (rqlite, a partir de um problema real de clustering em um emprego real). Depois, outros a reconstroem para atender às suas restrições de empacotamento: o dqlite da Canonical é uma biblioteca que você embute porque a Canonical precisava de um banco dentro dos seus produtos, enquanto o rqlite é um servidor que você roda ao lado do produto de qualquer pessoa. Depois, alguém argumenta que o caso comum é menor do que a solução principiada assume (Litestream), se prova certo, e o campo inteiro se recalibra. Por fim, as plataformas embrulham tudo e vendem. Se você trabalha com infraestrutura por tempo suficiente, vai ver esse filme de novo, como agentes de LLM estão reaprendendo as lições de sistemas distribuídos agora mesmo.
Minha recomendação sem rodeios, depois de tudo isso: comece com SQLite de nó único mais streaming do WAL para object storage. É impressionante até onde isso leva você, e a sua história de falha é uma restauração, não um postmortem de consenso. Passe para um sistema baseado em Raft só quando conseguir declarar, em uma frase, o requisito de disponibilidade que o streaming não atende, e aceite a conta de latência de escrita e operações de quórum que vem junto. Vá para o Postgres no momento em que precisar da superfície SQL dele ou de throughput de múltiplos escritores. E se nada disso servir, o mundo dos bancos embutíveis tem outras opções, de bancos de grafos embutíveis ao canto local-first dos CRDTs.
O resumo desmistificador: SQLite distribuído não é novo, não é um Postgres barato, não é um único design, não fica seguro por causa de um wrapper gerenciado e não é um upgrade grátis sobre backups. É um espaço de design com doze anos, bem mapeado, com três cantos, cada um correto para uma pergunta diferente. Os engenheiros que se queimam são os que nunca escreveram a pergunta.


