O Cloudflare KV é vendido como um store globalmente distribuído, e essa descrição é tecnicamente correta. O que ela omite é que "globalmente distribuído" se aplica integralmente às leituras, e só parcialmente às escritas — com um delay de até 60 segundos que muda tudo sobre como você deve usá-lo.
Quando você escreve uma chave no KV, a escrita vai para um store central. A partir daí, ela se propaga para todos os pontos de presença da Cloudflare — mais de 300 PoPs distribuídos globalmente. Essa propagação não é instantânea. A documentação oficial indica até 60 segundos para que todos os PoPs recebam o valor novo. Durante essa janela, um Worker rodando em Frankfurt pode retornar o valor antigo enquanto um Worker em São Paulo já enxerga o novo. Dois Workers na mesma região podem divergir se um deles ainda não recebeu a atualização.
Isso é consistência eventual. A Cloudflare documenta esse comportamento claramente, mas a frase "globalmente distribuído" é sedutora o suficiente para que muitos times não leiam essa parte até depurar um bug em produção.
O que acontece em uma leitura
A leitura no KV tem dois caminhos, e a diferença entre eles importa para latência. Quando um Worker faz env.MY_KV.get('chave'), o runtime verifica se aquela chave está em cache no PoP que está servindo o request. Se estiver — e a maioria das chaves quentes vai estar — a leitura retorna em sub-milissegundo, direto da memória do PoP. Esse é o caminho feliz e é o que torna o KV excepcionalmente rápido para leituras.
Se a chave não estiver em cache naquele PoP — porque é uma chave nova, porque foi escrita recentemente e ainda não propagou, ou porque o PoP simplesmente não recebeu aquela entrada — o runtime busca no store central. Isso adiciona cerca de 20ms. Não é dramático, mas é mensurável, e você vai ver esse número aparecer em trace quando a chave for fria.
O detalhe que gera surpresa: não há garantia de read-your-writes. Você escreve uma chave e imediatamente tenta lê-la na mesma invocação de Worker. A leitura pode retornar o valor anterior. Esse comportamento está documentado e é intencional — é a consequência direta da arquitetura de cache por PoP. Se você precisa de read-your-writes, o KV não é a ferramenta certa para aquele fluxo.
Para qual workload o KV foi construído
A arquitetura do KV faz sentido perfeito quando você conhece o problema que ela resolve: dados escritos com frequência baixa e lidos com frequência altíssima. O modelo econômico reforça esse padrão. Leituras custam $0.50 por milhão após os primeiros 10 milhões mensais gratuitos. Escritas custam $0.50 por milhão após o primeiro milhão gratuito. No tier free, você tem 100 mil leituras por dia e apenas 1 mil escritas por dia.
O custo e os limites apontam para o mesmo workload: escreva pouco, leia muito. Feature flags são o exemplo canônico. Um arquivo JSON com flags de produto muda algumas vezes por dia, no máximo. Mas é lido por cada request de cada Worker em cada PoP do mundo. A propagação de 60 segundos é aceitável para uma flag — você não precisa que todos os usuários do planeta vejam a feature ao mesmo milissegundo. O número de leituras, potencialmente bilhões por mês, é servido de cache com custo mínimo.
O mesmo raciocínio se aplica a templates HTML renderizados, configuração de aplicação, dados de catálogo com baixa frequência de atualização e tokens de sessão com TTL definido. Você escreve uma vez, lê dezenas de milhares de vezes, e o KV entrega isso com latência de cache.
Onde o KV vai trair você
Qualquer workload que exige consistência imediata vai produzir bugs quando implementado sobre KV. O caso mais comum é o de sessão de usuário com estado mutável. O usuário faz logout; você escreve a flag de sessão inválida no KV; nos próximos 60 segundos, um PoP diferente pode ainda autenticar requests com o token antigo porque não recebeu a atualização.
Contadores exatos são outro ponto de falha. KV não tem operações atômicas — não existe compare-and-swap, não existe incremento atômico. Dois Workers lendo o mesmo contador simultaneamente vão ler o mesmo valor, incrementar independentemente e um dos incrementos vai ser perdido. Para contadores de rate limiting que precisam ser exatos, o KV é a ferramenta errada. Durable Objects existem para esse caso.
Dados que mudam por request também não se encaixam. Se cada resposta ao usuário altera um valor no KV, você está pagando $0.50 por milhão de escritas em volume que pode ser gigantesco, com latência de ~150ms por escrita para confirmação no store central, mais o delay de propagação. O custo escala de forma que não faz sentido econômico, e a latência de escrita vai aparecer na cauda de p99 dos seus requests.
Para consistência imediata por chave com baixa latência de escrita, D1 com a Sessions API é o caminho atual da Cloudflare. Para estado compartilhado que requer operações atômicas, Durable Objects.
O modelo de custo sem ilusões
O free tier é generoso para experimentação mas estreito para produção com qualquer volume. 100 mil leituras por dia equivalem a pouco mais de 1 request por segundo constante — uma aplicação real com tráfego razoável passa disso em minutos.
No paid tier, o que muda é que as leituras ficam praticamente gratuitas em escala. $0.50 por milhão de leituras é barato o suficiente para não aparecer como linha relevante no bill se seu workload for corretamente read-heavy. As escritas a $0.50 por milhão, com 1 milhão livre por mês, cobrem a maioria dos padrões de config e flags sem custo significativo.
O que pode surpreender é o storage: $0.50 por GB-mês além do primeiro GB gratuito. Para valores pequenos — JSON de configuração, tokens, flags — você dificilmente vai tocar esse limite. Para quem considera armazenar binários de tamanho considerável no KV (o limite por valor é 25MB), o custo de storage começa a aparecer. Para arquivos grandes, R2 a $0.015/GB faz mais sentido.
O que o KV resolve bem e o que não resolve
O KV é uma ferramenta de leitura de alta performance com escrita eventual. Quando você aceita esse modelo, ele entrega sub-milissegundo de latência para leituras quentes, distribuição global automática sem configurar replicação, e um modelo de preço que favorece reads em volume massivo.
O erro não é usar KV — é usá-lo como se fosse um banco de dados de propósito geral. Nenhuma ferramenta substitui o diagnóstico correto do workload. Se seus dados mudam com frequência por usuário, exigem atomicidade ou precisam de consistência imediata, o KV não vai atender — e você vai descobrir isso em produção, não no desenvolvimento.
Leia também
- KV em produção: os padrões que funcionam e os que enganam no início
- Invalidação de cache no KV: o problema que ninguém resolve com elegância
- KV para rate limiting, feature flags e configuração distribuída: onde funciona e onde quebra
- Cloudflare D1: o banco SQLite no edge — e por que 'edge' não significa o que parece
- Cloudflare Workers vs Pages: a diferença que importa antes de você escolher
- KV vs R2 vs Cache API: quando usar cada camada de armazenamento do Cloudflare