SQLite em produção: casos reais onde faz sentido

1. Quando o SQLite supera o modelo cliente-servidor

SQLite é frequentemente subestimado como uma "solução de brinquedo", mas em cenários específicos ele supera bancos cliente-servidor tradicionais como PostgreSQL ou MySQL. O segredo está em entender onde a simplicidade é uma vantagem competitiva.

Aplicações embarcadas e IoT são o caso clássico. Dispositivos com 64 MB de RAM e processadores ARM Cortex-M não podem rodar um servidor PostgreSQL. SQLite ocupa menos de 600 KB e funciona com zero configuração. Um sensor de temperatura que armazena leituras a cada 5 minutos — SQLite lida perfeitamente com esse padrão.

Ferramentas desktop e aplicações offline-first formam outro nicho forte. O Notion armazena dados localmente em SQLite antes de sincronizar com a nuvem. O Obsidian usa SQLite como mecanismo de busca e metadados. O padrão é claro: quando o usuário precisa de funcionalidade completa sem conexão de rede, SQLite brilha.

Serviços com baixo volume de escrita também se beneficiam. Um servidor web que recebe 10 requisições por segundo, onde 90% são leituras — SQLite com WAL (Write-Ahead Logging) entrega latências abaixo de 1 ms. O gargalo não é o banco, é a rede.

-- Exemplo: Configuração otimizada para produção com SQLite
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA cache_size = -64000;  -- 64 MB de cache
PRAGMA busy_timeout = 5000;  -- 5 segundos de espera
PRAGMA foreign_keys = ON;

2. Casos de sucesso reais com SQLite em produção

O próprio SQLite.org usa SQLite em produção. O Fossil SCM, sistema de versionamento criado por D. Richard Hipp (autor do SQLite), armazena todo o repositório em um único arquivo SQLite. Milhares de commits, branches e issues — tudo em um banco de 50 MB que roda sem servidor.

Dispositivos móveis são o maior caso de sucesso invisível. Cada aplicativo Android e iOS pode usar SQLite localmente. O WhatsApp armazena mensagens em SQLite no celular do usuário. Quando você envia "bom dia" para 5 grupos, o SQLite está ali, escrevendo 5 registros em microssegundos.

Aplicações de análise local como o Datasette transformam SQLite em uma ferramenta de análise de dados. Cientistas de dados exportam CSVs para SQLite e executam consultas SQL complexas sem depender de um servidor central. O Litestream permite fazer backup contínuo desses bancos para S3, garantindo durabilidade.

-- Exemplo: Consulta analítica em SQLite com dados de vendas
SELECT 
    strftime('%Y-%m', data_venda) AS mes,
    COUNT(*) AS total_vendas,
    SUM(valor) AS receita_total,
    AVG(valor) AS ticket_medio
FROM vendas
WHERE data_venda >= '2024-01-01'
GROUP BY mes
ORDER BY mes;

3. Arquiteturas híbridas: SQLite + banco central

A estratégia mais madura não é substituir o banco central, mas complementá-lo. SQLite como cache local de leitura em edge computing reduz latência drasticamente. O LiteFS sincroniza réplicas locais de SQLite a partir de um nó primário, permitindo que servidores em diferentes regiões atendam requisições sem latência de rede.

Réplicas de leitura com Litestream resolvem o problema de backup. Configure o Litestream para replicar continuamente seu SQLite para S3 ou GCS. Se o servidor falhar, restaure o banco em segundos. O custo é irrisório comparado a um RDS multi-AZ.

Sincronização bidirecional com Postgres é possível via ferramentas como pg2sqlite. Aplicações offline-first sincronizam dados locais (SQLite) com o servidor central (Postgres) quando a conexão é restabelecida. O usuário nunca percebe a diferença.

-- Exemplo: Configuração do Litestream para replicação contínua
dbs:
  - path: /data/app.db
    replicas:
      - url: s3://meu-bucket/litestream/app
        retention: 72h
      - url: gcs://meu-bucket/litestream/app
        retention: 24h

4. Limitações críticas e mitos comuns

Concorrência de escrita é a maior limitação. SQLite usa bloqueio de nível de banco para escritas. No modo WAL, leitores não bloqueiam escritores, mas apenas uma transação de escrita ocorre por vez. Para aplicações com 100 escritas concorrentes por segundo, o gargalo aparece.

Tamanho do banco é outro ponto de atenção. SQLite funciona bem até 10 GB. Acima disso, operações como VACUUM e backups tornam-se lentas. Bancos de 50 GB podem levar minutos para compactar.

Ausência de gerenciamento de usuários é um mito parcial. SQLite não tem GRANT/REVOKE, mas você pode implementar controle de acesso na aplicação. Para ambientes com múltiplos usuários concorrentes, isso exige disciplina.

-- Exemplo: Verificando o tamanho do banco e páginas livres
PRAGMA page_count;
PRAGMA page_size;
-- Calcular tamanho real: page_count * page_size / 1048576 (MB)

5. Estratégias para escalar SQLite em produção

Particionamento por cliente é a abordagem mais comum. Cada cliente tem seu próprio arquivo SQLite. Um SaaS com 10.000 clientes teria 10.000 arquivos de banco, cada um com 50 MB. Isso escala horizontalmente sem esforço.

Uso de Raft ou LiteFS permite replicação multi-nó. O LiteFS usa Raft para eleger um primário que aceita escritas. Os secundários servem leituras. Se o primário falha, um secundário assume em segundos.

Combinação com Redis resolve o problema de leituras intensas. Cacheie consultas frequentes no Redis e use SQLite como fonte da verdade. Um dashboard que atualiza a cada 30 segundos — Redis entrega em 1 ms, SQLite atualiza o cache em background.

-- Exemplo: Estrutura de diretórios para sharding por cliente
/data/
  clientes/
    001/
      app.db
      wal/
    002/
      app.db
      wal/
  logs/
    acesso.log

6. Quando evitar SQLite: cenários de alto risco

Sistemas com alta concorrência de escrita são inadequados. Uma rede social com 10.000 posts por minuto — SQLite trava. Cada post requer uma transação, e apenas uma ocorre por vez. O throughput máximo é de ~50 transações/segundo em hardware comum.

Aplicações que exigem transações distribuídas também não funcionam. SQLite não suporta two-phase commit entre bancos diferentes. Se você precisa de consistência entre SQLite e um banco remoto, prepare-se para complexidade extra.

Ambientes com compliance e auditoria em tempo real são arriscados. Sem triggers de auditoria nativos e sem logs de transação detalhados, atender requisitos SOX ou PCI-DSS exige implementação manual que pode introduzir bugs.

-- Exemplo: Simulando concorrência (não recomendado para produção)
-- Apenas uma transação por vez é processada
BEGIN IMMEDIATE;
INSERT INTO logs (usuario, acao) VALUES ('joao', 'login');
COMMIT;
-- Outra transação espera até a primeira terminar

7. Checklist para decidir se SQLite é a escolha certa

Volume de dados esperado — abaixo de 10 GB e crescimento previsível? SQLite funciona. Acima disso, considere particionamento ou migração.

Número de conexões simultâneas — até 10 escritores concorrentes? SQLite com WAL aguenta. Acima de 50, avalie bancos cliente-servidor.

Padrão de acesso — 90% leitura e 10% escrita? SQLite é ideal. Escrita intensa? Evite.

Replicação geográfica — necessária? LiteFS resolve. Backup point-in-time? Litestream cobre. Sem esses requisitos? SQLite puro é suficiente.

-- Checklist final em formato de consulta SQL simulada
SELECT
    CASE 
        WHEN volume_dados_gb < 10 THEN 'OK'
        ELSE 'Avaliar particionamento'
    END AS tamanho,
    CASE 
        WHEN escritas_por_segundo < 50 THEN 'OK'
        ELSE 'Considerar banco cliente-servidor'
    END AS concorrencia,
    CASE 
        WHEN leituras_por_escrita > 9 THEN 'Ideal'
        ELSE 'Monitorar performance'
    END AS padrao_acesso;

SQLite não é um banco de brinquedo. É uma ferramenta de precisão para problemas específicos. Use onde a simplicidade é uma vantagem, não uma limitação.

Referências