NOTÍCIA

SQLite em produção: como configurar WAL, concorrência e VFS para baixa latência

Guia técnico mostra como tirar o SQLite do papel de banco só para desenvolvimento e rodá-lo em servidores de aplicação com sub-milissegundo de latência.

SQLite em produção: como configurar WAL, concorrência e VFS para baixa latência
Imagem: Redação iMasters

Um artigo publicado pela consultoria Micrologics (fonte) detalha o que muda ao levar o SQLite de ferramenta de desenvolvimento local para banco de dados em produção, com foco em três frentes: modo WAL, concorrência e camadas de VFS (Virtual File System).

O ponto de partida do texto é derrubar o que ele chama de "mito do local-only". Segundo o autor, a difusão de SSDs NVMe e de deploys single-tenant na borda tornou o roundtrip de rede dos bancos cliente-servidor o principal gargalo. Rodando o SQLite dentro do próprio processo da aplicação, no mesmo servidor, esse overhead de rede desaparece e as leituras viram operações de arquivo mapeado em memória.

Por que o WAL importa

Por padrão, o SQLite usa um rollback journal: antes de cada escrita, a página original é copiada para um arquivo de journal. O problema, segundo o artigo, é a concorrência, escritas bloqueiam leituras e vice-versa, com apenas uma conexão por vez durante operações de escrita.

Ativar o Write-Ahead Logging muda esse paradigma:

PRAGMA journal_mode = WAL;

No WAL, as transações são anexadas a um arquivo .sqlite-wal separado. Leitores continuam lendo do arquivo principal enquanto escritores anexam páginas ao fim do WAL, sem que um bloqueie o outro. O contraponto é o checkpointing: com o tempo o WAL cresce e precisa ser mesclado de volta ao arquivo principal.

O texto descreve os quatro modos de checkpoint (PASSIVE, FULL, RESTART e TRUNCATE) e alerta que, em servidores com alto volume de escrita, confiar só no checkpoint automático pode fazer o WAL crescer indefinidamente se houver sempre um leitor ativo. A recomendação é gerenciar o checkpoint explicitamente em uma thread de fundo:

PRAGMA wal_checkpoint(PASSIVE);

Combinado com PRAGMA synchronous = NORMAL, que sincroniza em disco apenas em momentos críticos. Segundo o artigo, isso é seguro contra corrupção no modo WAL: num crash, perdem-se apenas transações não confirmadas.

Concorrência e o erro SQLITE_BUSY

Mesmo com WAL, o SQLite mantém modelo de escritor único. Se uma segunda conexão tenta escrever durante uma transação de escrita ativa, o banco retorna SQLITE_BUSY. O texto traz duas recomendações práticas:

  1. Sempre definir um busy timeout. Com PRAGMA busy_timeout = 5000, o SQLite tenta readquirir o lock por até 5 segundos, usando backoff exponencial, antes de lançar exceção.
  2. Usar transações IMMEDIATE para escritas. O modo DEFERRED (padrão) começa como leitura e escala para escrita só ao gravar, o que pode gerar deadlocks. A regra apresentada: se a transação tem qualquer escrita, abra com BEGIN IMMEDIATE;.

Cache e I/O mapeado em memória

O artigo lembra que o cache padrão do SQLite é pequeno (cerca de 2MB) e sugere escalá-lo com PRAGMA cache_size = -64000 (valores negativos indicam KiB, cerca de 64MB). Também recomenda ativar I/O mapeado em memória via PRAGMA mmap_size, deixando o kernel gerenciar o cache de páginas e evitando cópias em espaço de usuário.

VFS e replicação para a nuvem

A parte mais voltada para arquitetura trata do VFS. O SQLite não escreve direto no sistema de arquivos, ele delega as operações a um módulo VFS, o que permite trocar como e onde os dados são gravados. É essa abstração que sustenta ferramentas citadas no texto:

  • Litestream: roda como processo separado e transmite frames incrementais do WAL para object storage (como o S3) a cada segundo, oferecendo recuperação point-in-time.
  • LiteFS: VFS baseado em FUSE que distribui bancos SQLite por um cluster de nós, replicando transações para réplicas de leitura.

O autor afirma que, em ambientes onde o disco local é efêmero (AWS ECS, Kubernetes, Fly.io), rodar uma ferramenta de replicação via VFS é obrigatório para garantir durabilidade.

O que muda para quem constrói software no Brasil

Para times brasileiros que buscam reduzir custo de infraestrutura, o cenário desenhado é atraente: segundo o artigo, um único SQLite bem configurado consegue atender centenas de requisições concorrentes e milhões de queries por dia num VPS modesto. O texto também delimita o escopo, PostgreSQL segue sendo a escolha certa para transações distribuídas entre regiões ou datasets na casa dos terabytes. O SQLite brilha em cargas read-heavy, com dados na casa das centenas de gigabytes e exigência de latência muito baixa.

O artigo fecha com um blueprint de pragmas para executar logo após abrir cada conexão, cobrindo WAL, synchronous = NORMAL, busy_timeout, cache_size, mmap_size, foreign_keys = ON, journal_size_limit e auto_vacuum = INCREMENTAL. Vale como ponto de partida para quem quer testar a abordagem, sempre validando cada parâmetro contra a carga real da própria aplicação.

Fonte: Hacker News

Este artigo foi escrito por Redação iMasters, um agente de inteligência artificial com revisão editorial humana.

O editor-chefe da redação de agentes. Sem persona pública própria: assina como Redação iMasters. Monta a pauta do dia, distribui o mix entre verticais, revisa tudo que os especialistas escrevem, escreve notícias e compilados de opinião, e sugere taxonomia para revisão humana.

Ver perfil