Chamar o D1 de "banco de dados no edge" cria uma expectativa que a arquitetura não cumpre completamente. A imagem mental é de SQLite rodando em todos os 300 data centers da Cloudflare simultaneamente, com suas queries respondendo do ponto geograficamente mais próximo do usuário. A realidade é mais restrita: existe uma região primária onde todas as escritas acontecem, e réplicas de leitura espalhadas pela rede que recebem essas escritas com atraso de até 60 segundos. Se seu banco primário está na América do Norte e você escreve de um Worker rodando em São Paulo, essa escrita percorre 80 a 150 milissegundos de ida e volta antes de ser confirmada. O quickstart não menciona isso.
A arquitetura real do D1
O D1 usa SQLite como motor de banco de dados — o mesmo SQLite que roda em browsers, dispositivos móveis e aplicações desktop. Sobre esse motor, a Cloudflare construiu uma camada de replicação: uma instância primária recebe todas as escritas e propaga as mudanças para réplicas de leitura distribuídas pela rede global.
Quando você cria um banco D1, escolhe (ou deixa a Cloudflare escolher automaticamente) a região primária. Essa escolha determina onde as escritas pousam. Uma leitura feita por um Worker rodando em São Paulo pode ser atendida por uma réplica próxima, com latência adicional de 5 a 20 milissegundos sobre o tempo de execução do Worker. Uma escrita feita pelo mesmo Worker vai até a região primária — e se essa região for us-east-1, o round-trip é de 80 a 150ms só de rede antes de você receber a confirmação.
O prazo de propagação das réplicas é relevante em produção: uma escrita no primário pode levar até 60 segundos para aparecer em todas as réplicas. Durante esse intervalo, um Worker que lê de uma réplica desatualizada enxerga dados anteriores à escrita. Esse comportamento é chamado de consistência eventual — a réplica vai convergir para o estado correto, mas não imediatamente.
O problema de consistência que você vai encontrar em produção
O padrão que quebra com consistência eventual é o de escrita seguida imediatamente de leitura. Você cria um usuário, redireciona para a página de perfil, e a query que carrega o perfil bate em uma réplica que ainda não recebeu o INSERT. O resultado é um perfil vazio, ou um erro 404, ou um estado inconsistente que o usuário vê e não entende.
Esse problema existe em qualquer banco com replicação — mas com D1 ele aparece sem aviso porque a abstração do binding esconde qual réplica está sendo consultada. A Cloudflare criou a Sessions API exatamente para esse caso: dentro de uma mesma sessão D1, uma escrita garante que a leitura subsequente veja os dados escritos, independente de qual réplica atende a query.
A Sessions API funciona criando uma sessão com env.DB.withSession(). Dentro do callback, todas as queries compartilham o contexto de sessão e o D1 garante que leituras pós-escrita retornem dados atualizados. Para fluxos que combinam escrita e leitura imediata — criação de conta, atualização de configurações, finalização de pedido — usar Sessions API é o caminho direto para evitar inconsistências visíveis ao usuário.
Para fluxos puramente de leitura, como listagens e dashboards, a consistência eventual não é problema: os dados têm margem de alguns segundos de atraso sem impacto percebido.
Preço real: quando o tier gratuito deixa de ser suficiente
O tier gratuito do D1 entrega 5GB de armazenamento, 5 milhões de linhas lidas por dia e 100 mil linhas escritas por dia. Esses números soam generosos em abstrato, mas o custo de leitura do D1 não é baseado em linhas retornadas — é baseado em linhas examinadas pelo motor de banco.
Uma query que varre 100 mil linhas para retornar 5 mil consome 100 mil leituras, não 5 mil. Uma aplicação com mil usuários ativos fazendo queries de listagem sem índices adequados pode esgotar as 5 milhões de leituras diárias em poucas horas. O tier gratuito é suficiente para desenvolvimento, ferramentas internas de baixo volume e protótipos — não para aplicações com tráfego real de usuários.
Quando o tier gratuito não basta, o próximo passo requer o plano Workers Paid ($5/mês pela plataforma) mais os custos variáveis do D1: $0,001 por milhão de linhas lidas, $1 por milhão de linhas escritas e $0,75 por GB-mês de armazenamento. O custo de escritas tem uma aritmética simples: um fluxo de cadastro que insere 10 linhas por usuário chega a $10 em custos de escrita por cada milhão de usuários cadastrados. Para aplicações com crescimento rápido, esse número aparece antes do esperado.
O custo de leituras depende quase completamente da qualidade dos índices. Com índices adequados, uma query que retorna 20 linhas lê 20 linhas. Sem índices, a mesma query pode ler 500 mil linhas e custar 500 vezes mais.
Como planejar a região primária antes de criar o banco
A região primária do D1 é uma decisão irreversível na criação do banco. Não existe opção de mover o primário depois — a alternativa é exportar os dados, criar um novo banco na região desejada e importar. Isso torna a escolha da região uma das poucas decisões de infraestrutura que exige atenção antes de escrever a primeira linha de código.
A regra prática: a região primária deve ser onde a maioria das escritas se origina. Para um produto brasileiro com usuários brasileiros, o Worker provavelmente roda no PoP de São Paulo (GRU) ou similar. A Cloudflare oferece southamerica-east1 como opção de região primária D1 — escolher essa região para um produto brasileiro reduz a latência de escrita de 80-150ms para 5-20ms.
Para verificar qual região faz mais sentido, meça a latência de rede do Worker para a região candidata usando um simples fetch com timestamp antes e depois. O custo de uma escolha errada de região primária não aparece no desenvolvimento — aparece quando a aplicação está em produção e cada escrita adiciona 100ms de latência perceptível ao usuário.
O limite de 2GB por banco e 10 bancos no plano pago também entra no planejamento inicial. Se a aplicação tende a crescer além de 2GB, o particionamento de dados entre múltiplos bancos D1 precisa ser pensado antes de os primeiros dados chegarem — refatorar esse particionamento depois, com dados em produção, é consideravelmente mais trabalhoso.
Leia também
- Cloudflare KV: o que globalmente distribuído significa quando você precisa escrever
- D1 em produção: performance, limites e o que não escala sozinho
- Migrations em D1: como versionar schema e o que acontece quando dá errado
- Cloudflare Durable Objects: estado consistente no edge — o que realmente muda
- Cloudflare Workers em produção: o que muda depois do hello world
- Cloudflare Workers vs Pages: a diferença que importa antes de você escolher