PostgreSQL vs CockroachDB para disponibilidade multi-regional
PostgreSQL vs CockroachDB: uma comparação prática de consistência, latência, mudanças de esquema e os custos operacionais reais de ir multi-região cedo.

Qual problema você realmente está tentando resolver?
"Disponibilidade multi-regional" é usado para significar vários objetivos diferentes. Misturar esses objetivos é como equipes acabam escolhendo o banco errado.
Antes de comparar PostgreSQL e CockroachDB, escreva (1) a falha específica que você quer sobreviver e (2) o que os usuários devem experimentar enquanto essa falha estiver acontecendo.
A maioria das equipes persegue alguma combinação de:
- Maior uptime quando uma região cai (failover)
- Respostas mais rápidas para usuários longe da sua região principal (menor latência)
- Regras de dados ligadas à geografia (localidade ou residência)
- Comportamento previsível sob carga, não apenas em testes no caminho feliz
O objetivo compartilhado é simples: um cliente em outro continente ainda deve obter resultados rápidos e corretos.
A parte difícil é que "rápido" e "correto" podem entrar em conflito quando você espalha gravações entre regiões. Consistência mais forte geralmente significa mais coordenação entre regiões, e isso acrescenta latência. Reduzir latência normalmente significa ler de uma cópia próxima ou usar replicação assíncrona, o que pode levar a leituras defasadas ou ao tratamento de conflitos que passa a ser sua responsabilidade.
Um exemplo concreto: um usuário na Alemanha atualiza seu endereço de entrega e em seguida finaliza a compra. Se o checkout ler de uma réplica nos EUA que está alguns segundos atrás, o pedido pode usar o endereço antigo. Alguns produtos toleram isso com UX clara e tentativas/retries. Outros (pagamentos, estoque, conformidade) não podem tolerar.
Não existe uma escolha universalmente melhor. A resposta certa depende do que nunca pode estar errado, do que pode ser um pouco mais lento e de quanta complexidade operacional sua equipe consegue lidar diariamente.
Duas abordagens para "disponível em várias regiões"
Quando as pessoas comparam PostgreSQL vs CockroachDB para uso multi-região, frequentemente estão comparando dois designs diferentes.
No PostgreSQL, a configuração mais comum é primária única. Uma região é a "casa" onde acontecem as gravações. Outras regiões rodam réplicas de leitura que copiam mudanças da primária. Se a região primária falha, você promove uma réplica em outro lugar e aponta a aplicação para ela. Feito corretamente, isso pode funcionar muito bem, mas o sistema ainda está organizado em torno de um único local de escrita principal mais um plano de failover deliberado.
Com sistemas distribuídos SQL como o CockroachDB, o banco é projetado para espalhar dados e responsabilidades entre regiões desde o dia um. Os dados são copiados para múltiplos nós e o cluster concorda sobre a ordem das gravações. Você pode frequentemente colocar certos dados mais perto dos usuários em diferentes regiões mantendo um banco lógico único.
O que muda para a equipe de aplicação é menos a sintaxe SQL e mais as expectativas:
- Writes: gravações no PostgreSQL são mais rápidas perto da primária. Gravações no CockroachDB muitas vezes exigem acordo de múltiplas réplicas, que podem incluir confirmações entre regiões.
- Reads: PostgreSQL pode servir leituras locais a partir de réplicas (com o tradeoff de defasagem). CockroachDB pode servir leituras consistentes, mas pode pagar custo de coordenação dependendo de como os dados são posicionados.
- Falhas: failover no PostgreSQL é uma troca que você aciona e gerencia. CockroachDB é construído para continuar rodando através de algumas falhas regionais, mas apenas dentro de suas regras de replicação e quórum.
O requisito oculto é correção durante falhas. Se você tolera leituras brevemente defasadas, ou uma pequena pausa nas gravações durante um failover, PostgreSQL com primária única pode ser uma boa escolha. Se você precisa que o sistema permaneça correto e gravável enquanto uma região estiver fora, você aceita o custo de coordenação de um banco distribuído.
Garantias de consistência: no que você pode confiar
Consistência, em termos simples: quando alguém atualiza um registro, todo mundo deveria ver a mesma verdade.
No PostgreSQL, consistência forte é mais simples quando sua aplicação fala com uma única primária. Leituras e gravações ocorrem em um só lugar, então transações se comportam de forma previsível. Você pode adicionar réplicas para acelerar leituras em outras regiões, mas então precisa decidir quando é aceitável ler dados levemente defasados.
No CockroachDB e outros sistemas SQL distribuídos, consistência forte também é possível, mas fica mais cara à medida que você espalha dados por regiões distantes. Gravações que precisam ser consistentes entre regiões exigem coordenação entre nós. Quanto mais distantes suas regiões, maior a latência dessa coordenação. Você frequentemente sentirá isso como gravações mais lentas e transações mais longas, especialmente quando uma transação toca linhas que vivem em regiões diferentes.
Ambos os sistemas podem suportar transações serializáveis (o banco se esforça para que mudanças concorrentes se comportem como se tivessem ocorrido uma por vez). A diferença é onde o trabalho acontece: o PostgreSQL paga a maior parte do custo dentro de uma região, enquanto um sistema distribuído pode pagar esse custo através das regiões.
Algumas perguntas deixam os tradeoffs concretos:
- Usuários podem ver leituras defasadas, ainda que por alguns segundos?
- Duas regiões podem aceitar gravações de forma independente, ou toda gravação precisa ser aceita globalmente?
- O que acontece se duas pessoas editam o mesmo registro ao mesmo tempo? Você permite conflitos?
- Quais ações devem estar corretas sempre (pagamentos, permissões) versus "eventualmente ok" (analytics)?
- Você precisa de uma verdade global, ou "verdade local" é aceitável para alguns dados?
Expectativas de latência: o que os usuários vão sentir
Um modelo mental útil: distância adiciona tempo, e coordenação adiciona mais tempo. Distância é física. Coordenação é o banco esperando outros nós para concordarem antes de declarar "pronto".
Com um setup PostgreSQL de região única, a maior parte do trabalho acontece perto. Leituras e gravações normalmente completam em uma única ida e volta da sua aplicação ao banco. Se você colocar uma réplica de leitura em outra região, leituras podem ser locais, mas gravações ainda vão para a primária e réplicas estão sempre pelo menos um pouco atrasadas.
Em um sistema distribuído como CockroachDB, os dados são espalhados entre regiões. Isso pode tornar algumas leituras rápidas quando os dados necessários estão próximos. Mas muitas gravações precisam ser confirmadas por maioria das réplicas. Se seus dados são replicados entre continentes, até uma gravação simples pode precisar de confirmações entre regiões.
Não julgue pela latência média. Olhe para a latência p95 (os 5% mais lentos). Usuários notam essas pausas. Uma página que normalmente carrega em 120 ms mas atinge 800 ms algumas vezes por dia parece instável, mesmo que a média esteja OK.
O que "rápido" significa depende da sua carga de trabalho. Aplicações com muitas gravações sentem mais o custo da coordenação. Aplicações focadas em leitura podem se beneficiar quando as leituras são locais. Transações maiores, fluxos multi-etapa e linhas "quentes" (muitos usuários atualizando o mesmo registro) tendem a amplificar a latência.
Ao avaliar PostgreSQL vs CockroachDB, mapeie suas principais ações de usuário (cadastro, checkout, busca, atualizações administrativas) para onde os dados vivem e quantas regiões devem concordar em cada transação. Esse exercício prevê o que os usuários vão sentir melhor do que benchmarks genéricos.
Tradeoffs operacionais: o que você vai gerenciar dia a dia
Listas de funcionalidades importam menos do que o que vai te acordar às 2 da manhã e o que sua equipe tem que fazer toda semana.
Operações com PostgreSQL são familiares e previsíveis. Multi-região geralmente significa que você também opera componentes de suporte: réplicas, ferramentas de failover, ou clusters regionais separados com roteamento na camada de aplicação. O trabalho frequentemente está em provar que o plano funciona (drills de failover, restores) em vez de ajuste de queries no dia a dia.
CockroachDB empurra mais da história multi-região para dentro do próprio banco. Isso pode reduzir o número de componentes extras ao redor do banco, mas também significa que você precisa entender um sistema distribuído: saúde dos nós, replicação, rebalancing e o que o cluster faz sob estresse.
Na prática, equipes acabam fazendo as mesmas tarefas centrais em qualquer configuração:
- Planejar upgrades e validar drivers, monitoramento e automação
- Fazer backups e testar restores (não apenas checar que o backup existe)
- Praticar failover e documentar os passos exatos do runbook
- Investigar queries lentas e separar "query ruim" de latência cross-region
- Observar crescimento de armazenamento e comportamento de compactação a longo prazo
Os modos de falha parecem diferentes. Com PostgreSQL, uma queda de região muitas vezes dispara um failover deliberado. Você pode aceitar um período de modo somente leitura, latência elevada, ou funcionalidade reduzida. Em um banco distribuído, o caso mais difícil costuma ser uma divisão de rede. O sistema pode proteger consistência recusando algumas gravações até que o quórum esteja disponível.
Observabilidade também muda. Com uma primária única, você pergunta mais "Por que essa query está lenta?". Com um cluster distribuído, você também pergunta "Onde esses dados estão armazenados e por que a query cruzou regiões?".
Os custos aumentam de maneiras óbvias e não óbvias. Adicionar uma segunda região pode aumentar o número de nós, mas também aumenta monitoramento, complexidade de incidentes e tempo gasto explicando latência e comportamento de falha para equipes de produto.
Mudanças de esquema e migrações em um ambiente distribuído
Uma mudança de esquema é qualquer atualização na forma dos seus dados: adicionar uma coluna para uma flag de recurso, renomear um campo, mudar um tipo (int para string), adicionar um índice, ou introduzir uma nova tabela.
No PostgreSQL, migrações podem ser rápidas, mas o risco costuma ser tempo de lock e bloqueio de gravações. Algumas mudanças reescrevem uma tabela inteira ou mantêm locks por mais tempo do que o esperado, o que pode transformar um deploy normal em um incidente se ocorrer em pico de tráfego.
Em um banco distribuído, o risco muda. Mesmo quando mudanças de esquema online são suportadas, a alteração ainda precisa ser acordada entre nós e replicada entre regiões. Mudanças “simples” podem demorar mais para serem implantadas e mais para serem validadas. Você pode terminar o deploy e ainda passar tempo observando lag, hotspots e surpresas no plano de query em cada região.
Alguns hábitos tornam migrações monótonas:
- Prefira mudanças aditivas primeiro (nova coluna, nova tabela). Mude leituras e gravações depois. Remova campos antigos mais tarde.
- Mantenha cada migração pequena o suficiente para reverter rapidamente.
- Evite mudar tipos in-place quando possível. Backfill em uma coluna nova.
- Trate índices como um rollout de feature, não como um ajuste rápido.
- Pratique migrações com tamanhos de dados realistas, não bancos de teste vazios.
Exemplo: você adiciona preferred_language para usuários da UE. Adicione a coluna, grave nos campos antigo e novo por uma release, depois atualize a UI para ler o campo novo e só então faça a limpeza. Em setups multi-region, rollouts em etapas reduzem surpresas quando regiões alcançam estados diferentes em ritmos distintos.
O custo real de distribuir cedo
Escolher entre PostgreSQL e CockroachDB cedo não é só uma decisão de banco. Muda o quão rápido você entrega, com que frequência a produção te surpreende, e quanto tempo sua equipe passa mantendo o sistema estável em vez de construir features.
Se você pode atingir seus objetivos com uma região primária, manter a simplicidade normalmente vence no começo. Você tem menos partes móveis, falhas mais claras e debug mais rápido. Contratar também é mais fácil porque experiência profunda em PostgreSQL é comum, e desenvolvimento local e CI tendem a ser mais simples.
Equipes frequentemente permanecem centralizadas primeiro porque isso suporta iteração mais rápida, rollbacks mais simples e performance mais previsível. On-call é mais fácil quando há menos partes móveis.
Ir para distribuído cedo ainda pode ser a escolha certa quando os requisitos são reais e não negociáveis: metas rígidas de uptime entre regiões, necessidades legais de residência de dados, ou uma base global de usuários onde latência afeta receita.
O imposto da complexidade aparece em pequenas coisas que se acumulam: trabalho de feature demora mais porque você precisa considerar comportamento multi-região, testes precisam cobrir mais modos de falha, e incidentes demoram mais porque causas raiz podem ser temporização, replicação ou consenso em vez de "o banco está down". Mesmo mudanças básicas de esquema exigem mais cuidado.
Uma regra prática útil: valide demanda primeiro, depois distribua quando a dor for mensurável. Gatilhos comuns são SLOs de uptime perdidos consistentemente em uma região, queda de usuários devido a latência, ou requisitos de conformidade que bloqueiam contratos.
Se você está construindo com uma ferramenta como AppMaster, pode começar com um deploy mais simples enquanto refina workflows e modelos de dados, e então migrar para um plano multi-região quando produto e padrões de tráfego estiverem comprovados.
Um passo a passo para escolher entre eles
"Multi-região" fica mais claro quando você transforma isso em alguns números e alguns fluxos de usuário.
Passo a passo
- Escreva RPO e RTO em palavras simples. Exemplo: "Se uma região morrer, podemos perder até 1 minuto de dados (RPO) e devemos voltar em 15 minutos (RTO)." Se você não tolera perder gravações já confirmadas, diga isso explicitamente.
- Mapeie onde os usuários estão e marque ações críticas de escrita. Liste suas regiões e as ações principais: cadastro, checkout, reset de senha, postar um comentário, ver um feed. Nem todas as gravações são igualmente importantes.
- Defina necessidades de consistência por feature. Pagamentos, estoque e saldos de conta normalmente precisam de correção rigorosa. Feeds, analytics e "última vez visto" frequentemente aceitam pequenos atrasos.
- Defina um orçamento de latência e teste das regiões alvo. Decida o que "rápido o suficiente" significa (por exemplo, 200 a 400 ms para ações chave), depois meça o tempo de ida e volta das regiões que importam.
- Escolha um modelo operacional que sua equipe consiga suportar. Seja honesto sobre tempo de on-call, habilidade com bancos de dados e tolerância à complexidade.
Um exemplo rápido
Se a maioria dos usuários está nos EUA e só uma pequena parcela está na UE, você pode manter gravações em uma região primária, apertar metas de recuperação e adicionar otimizações de leitura na UE para telas não críticas. Se fluxos com muitas gravações na UE precisarem de melhor UX, considere uma camada de serviço na UE ou uma fila para manter a UI responsiva. Reavalie a escolha do banco quando correção multi-regional for necessária para tabelas centrais (contas, cobrança, permissões).
Cenário de exemplo: clientes nos EUA e na UE no mesmo produto
Imagine um SaaS B2B onde uma conta tem colegas em Nova York e Berlim. Todos veem os mesmos tickets, faturas e limites de uso. A cobrança é compartilhada, então um evento de pagamento deve impactar imediatamente o acesso para toda a conta.
Com PostgreSQL, um setup comum é uma primária nos EUA e réplicas de leitura na UE. Usuários nos EUA têm leituras e gravações rápidas. Usuários na UE podem ler localmente, mas qualquer coisa que precise estar correta naquele momento (plano atual, permissões mais recentes, status de fatura) frequentemente precisa atingir a primária nos EUA. Se leituras na UE vierem de uma réplica, você aceita que pode haver atraso. Isso pode parecer com um admin financeiro em Berlim pagando uma fatura, atualizando a página e ainda vendo "vencido" por um tempo.
Com um banco distribuído multi-região como CockroachDB, você pode colocar dados mais próximos de ambas regiões mantendo um banco lógico único. O tradeoff é que muitas gravações, e algumas leituras, precisam coordenar entre regiões para permanecer consistentes. Essa viagem extra entre regiões passa a fazer parte do caminho normal, especialmente para registros compartilhados como configurações de conta e cobrança.
Um plano em etapas que costuma funcionar:
- Comece com uma região e uma primária PostgreSQL, depois meça onde os usuários e gravações realmente estão.
- Adicione réplicas de leitura na UE para relatórios e telas não críticas.
- Se fluxos com muitas gravações na UE precisarem de UX melhor, considere uma camada de serviço na UE ou fila para que a UI continue responsiva.
- Reavalie a escolha do banco quando a correção multi-regional for necessária para tabelas centrais (contas, cobrança, permissões).
Se você constrói com AppMaster, manter a lógica em processos de negócio visuais pode facilitar mudanças futuras de regiões de deploy ou estratégia de banco.
Erros comuns que equipes cometem
O maior erro é assumir que "multi-região" automaticamente significa rápido para todo mundo. Um banco distribuído não vence a física. Se uma transação precisa confirmar em dois lugares distantes, o tempo de ida e volta aparece em toda gravação.
Outra armadilha comum é misturar expectativas de correção sem admitir isso. Equipes exigem precisão para saldos, estoque e permissões, mas tratam outras partes do app como "próximo o suficiente". Usuários então veem um valor em uma tela e outro valor no passo seguinte.
Padrões para observar:
- Esperar que todas as gravações pareçam locais mesmo quando exigem confirmação cross-region
- Tratar consistência eventual como detalhe de UI e descobrir que isso quebra regras de negócio (reembolsos, cotas, controle de acesso)
- Aprender a realidade operacional só depois do primeiro incidente (backups, upgrades, saúde de nós, falhas regionais)
- Subestimar quanto tempo leva para debugar transações lentas quando logs e dados estão espalhados por regiões
- Tratar a primeira decisão como permanente em vez de planejar um caminho de evolução
Migrações merecem atenção extra porque tendem a ocorrer quando o produto está crescendo mais rápido. Uma mudança de esquema fácil em um único nó pode se tornar arriscada quando deve permanecer consistente em muitos nós e regiões.
Trate a primeira escolha de banco como um passo, não um destino. Se você usa AppMaster, pode prototipar fluxos e modelos de dados rapidamente, validar latência real e comportamento em falhas antes de se comprometer com uma arquitetura distribuída complexa.
FAQ
Comece escrevendo a falha exata que você quer sobreviver (queda completa de uma região, perda de um nó de banco, ou divisão de rede entre regiões) e o que os usuários ainda devem conseguir fazer durante esse evento. Depois, defina metas claras de quanta perda de dados é aceitável (RPO) e quão rápido você precisa se recuperar (RTO). Com isso explícito, os tradeoffs entre PostgreSQL e CockroachDB ficam muito mais fáceis de avaliar.
PostgreSQL costuma ser uma boa escolha padrão se você puder manter uma região primária para gravações e aceitar um processo de failover curto durante a queda de uma região. É mais simples de operar, mais fácil de contratar pessoas com essa experiência e geralmente oferece latência de escrita menor perto da primária. Adicione réplicas de leitura em outras regiões quando quiser leituras mais rápidas, mas puder tolerar algum atraso de replicação.
CockroachDB tende a fazer mais sentido quando você realmente precisa que o sistema continue correto e aceitável para gravações enquanto uma região está fora, sem um failover manual de promover e trocar. O tradeoff é maior latência média de gravação e mais complexidade operacional, porque o banco precisa coordenar réplicas para manter consistência forte. É uma boa opção quando a correção multi-regional é um requisito rígido, não apenas um diferencial.
Um padrão comum é ter uma única primária PostgreSQL para leituras e gravações, mais réplicas de leitura em outras regiões para performance local. Direcione telas somente de leitura ou que podem tolerar leve defasagem para as réplicas, e direcione tudo que é crítico (como status de cobrança ou permissões) para a primária. Isso melhora a experiência do usuário sem assumir a complexidade de gravações distribuídas desde o início.
O atraso nas réplicas pode fazer com que usuários vejam dados antigos por curtos períodos, o que quebra fluxos se a próxima etapa assumir que a última gravação já está visível. Para reduzir o risco, mantenha leituras críticas na primária, projete a UX para tolerar atrasos breves em telas não-críticas e adicione tentativas ou pedidos de atualização onde fizer sentido. O essencial é decidir antecipadamente quais recursos podem ser “eventualmente consistentes” e quais não podem.
Gravações multi-regionais geralmente aumentam a latência porque o banco precisa confirmar a gravação com outras réplicas em regiões diferentes antes de dizer que está concluída. Quanto mais distantes as regiões, mais esse tempo de coordenação aparece na latência p95. Se seu app faz muitas gravações ou tem transações em vários passos que tocam linhas compartilhadas, as viagens extras de ida e volta ficam bastante perceptíveis para os usuários.
Foque na latência p95 das suas ações principais, não apenas médias ou benchmarks sintéticos. Meça tempos reais de leitura e gravação das regiões onde seus usuários estão e teste alguns fluxos críticos fim a fim (cadastro, checkout, mudança de permissão). Também simule pelo menos um modo de falha e registre o que os usuários veem, porque “funciona em condições normais” não é o mesmo que “funciona durante uma queda”.
No PostgreSQL, o ponto assustador costuma ser tempo de bloqueio e gravações bloqueadas durante certas mudanças de esquema em tabelas grandes. Em sistemas distribuídos, as mudanças podem continuar online, mas levar mais tempo para propagar e podem revelar hotspots ou alterações de plano de query em diferentes regiões. A abordagem mais segura em ambos os casos é migrações aditivas e em etapas que mantenham a aplicação compatível enquanto dados e tráfego convergem gradualmente.
Uma queda completa de região em PostgreSQL normalmente aciona um failover planejado, onde você promove uma réplica e troca a aplicação para a nova primária, às vezes com uma curta pausa nas gravações. Em um sistema distribuído, o cenário mais difícil é uma divisão de rede, onde o banco pode recusar algumas gravações para proteger a consistência até que seja possível alcançar quorum novamente. Seus runbooks devem cobrir ambos os tipos de evento, não apenas “o banco caiu”.
Sim, se você tratar isso como um caminho de evolução em vez de uma decisão definitiva. Comece com um modelo simples de escrita em uma região, mantenha o esquema limpo e torne necessidades multi-region explícitas por funcionalidade para não depender acidentalmente de leituras defasadas em fluxos críticos. Se você constrói com AppMaster, é possível iterar rápido em modelos de dados e lógica de negócio, validar latência e comportamento em falhas em testes similares a produção, e só então migrar para um plano multi-região mais complexo quando houver necessidade comprovada.


