Nos primeiros anos de cloud computing (2006-2010), a maioria das aplicações rodava em uma única região. Falha de região (raro mas não impossível — AWS US-East teve outages históricas em 2011, 2012, 2017, 2021) significava downtime do sistema. Para a maioria dos sistemas, isso era aceitável — usuários reclamavam mas voltavam. Para sistemas críticos (financeiro, infraestrutura, comunicação), não era.
Multi-region é a arquitetura que distribui sistema entre múltiplas regiões geográficas, com objetivo de continuar operando mesmo se uma região cai. É o nível final de redundância em escalabilidade — mais caro e complexo que multi-AZ, mas necessário para sistemas com SLA acima de 99.99% ou requirements regulatórios de soberania de dados.
A complexidade vem da física. Conceito 02 do módulo 06 mostrou: round-trip cross-region (Brasil → US, por exemplo) é 100-150 ms. Round-trip entre AZs mesmo região é 1-2 ms. Diferença de duas ordens de magnitude. Sistemas multi-region precisam tomar decisões qualitativamente diferentes — onde escrever, onde ler, como replicar, como lidar com partição de rede entre regiões.
Este conceito articula multi-region como decisão arquitetural. Os modelos canônicos (active-passive, active-active), o problema de write locality, replicação cross-region, CAP/PACELC aplicado em escala global, failover regional, e quando multi-region vale a complicação. O escopo é prático — multi-region não é necessário para a maioria dos sistemas, mas quando é, fazer errado é caríssimo.
Por que multi-region — e por que não
Multi-region é caro em dimensões qualitativas: latência maior, complexidade arquitetural, consistency models mais fracos, custos cloud maiores. Antes de adotar, articular se compensa.
Razões legítimas para multi-region:
SLA acima de 99.99%. Single-region multi-AZ entrega ~99.99% (algumas horas de downtime por ano). Acima disso, multi-region é necessário. Sistemas financeiros core (bolsas, bancos), provedores de cloud, infraestrutura crítica.
Latência cross-continental. Usuários em Tóquio acessando sistema em US-East pagam 150-200 ms por round-trip. Para SLO de latência baixa global, multi-region com PoPs próximos ao usuário é única opção. CDN (módulo 06 conceito 10) cobre estática; APIs dinâmicas precisam de multi-region.
Soberania de dados. Dados de cidadãos europeus na Europa (GDPR), brasileiros no Brasil (LGPD em alguns casos), russos na Rússia, chineses na China. Multi-region por jurisdição é única forma de cumprir.
Disaster recovery formal. Requirement regulatório ou contratual de RTO/RPO específicos (Recovery Time Objective / Recovery Point Objective). Backup em outra região é mínimo; multi-region active é melhor.
Razões más para multi-region:
"Vamos ser global um dia." Sistema atende usuários só no Brasil, mas adopta multi-region "para preparar". Custo agora; benefício hipotético; complexidade desperdiçada.
"Para impressionar." Sistemas adotam multi-region por marketing de "infraestrutura global", não por necessidade real.
Sem articular consistency requirements. Time decide multi-region sem entender que vai cair em consistency model mais fraco. Bugs aparecem em produção.
Os modelos canônicos
Há três modelos principais de deployment multi-region. Cada um com perfil próprio de complexidade, latência, e consistency.
Active-passive (warm standby)
Uma região é primária; outra(s) é passiva. Toda escrita vai para primária; passiva recebe replicação assíncrona. Em failover, passiva é promovida. Tráfego de leitura: tipicamente apenas primary (ou primary + reads from passive como otimização).
Ganhos: arquitetura simples; consistency forte na primária; failover bem-definido. Custos: passiva ociosa em operação normal (custo sem benefício); failover tem RTO (tempo de detectar + promover) — segundos a minutos; data loss possível (writes não replicados antes da falha).
Quando usar: SLA 99.99-99.999% sem necessidade de latência baixa cross-region; disaster recovery clássico.
Active-active simétrico
Múltiplas regiões aceitam writes simultaneamente. Replicação cross-region bidirecional. Cliente é roteado para região mais próxima; cada região serve completamente.
Ganhos: latência baixa para todos os usuários (geo-roteamento); tolerância a falha regional total; capacidade dobra. Custos: conflict resolution cross-region; consistency model eventual/causal (não linearizable globalmente); complexidade alta.
Quando usar: sistemas globais reais (SaaS B2C global, aplicações de mensageria, gaming); requirement de "near-zero downtime mesmo em falha regional".
Active-active sharded por geografia
Variante: cada região "domina" um conjunto de tenants/usuários (shard geográfico). Tenant A escreve sempre em sua região "home"; replicado para outras como read-only. Failover de região: tenants daquela região perdem acesso temporariamente (se passive standby não disponível).
Ganhos: writes localizados (sem conflict resolution complicado); compliance facilitada (dados em região correta); leitura cross-region disponível (com lag). Custos: failover de tenant entre regiões é complexo; balanceamento de carga desigual entre regiões.
Quando usar: SaaS multi-tenant com clientes geograficamente distribuídos (alguns na Europa, outros nos EUA, etc.); compliance regional importante.
Replicação cross-region — o problema central
Em qualquer modelo multi-region, dados precisam atravessar regiões em algum momento. Como?
Replicação assíncrona. Mais comum. Region A commita write localmente; envia stream para region B; B aplica em background. Latência cross-region não bloqueia o write em A. Custo: replication lag (módulo 03 e conceito 05 do módulo). B fica atrás de A; failover pode perder writes.
Replicação síncrona. Region A espera B confirmar antes de commitar. Garantia de durabilidade cross-region; nenhum dado perdido em failover. Custo: cada write paga round-trip cross-region (50-200 ms). Latência percebida pelo cliente vira inviável para a maioria dos sistemas.
Quórum global (ex.: Spanner, CockroachDB). Write commitado quando majoritário cross-region confirma. Spanner usa TrueTime + 2PC para consistency global linearizable. Custo: writes pagam pelo menos 1 RTT cross-region; latência escolhida pela arquitetura.
CRDTs (Conflict-Free Replicated Data Types). Estruturas de dados desenhadas para mesclar sem conflito. Counters distribuídos, sets, ordenações específicas. Útil em domínios onde semântica do conflito é definível matematicamente (likes, presença de usuário, colaboração tipo Google Docs).
Event sourcing + replicação de eventos. Aplicação grava eventos imutáveis localmente; eventos replicados cross-region; cada região reconstrói estado a partir do log. Conceito 12 do módulo cobre.
A escolha depende da semântica do dado. Saldo bancário: precisa consistency forte → quórum global ou single-region active. Likes em post: tolerância a inconsistência alta → CRDT eventual. Listagem de produtos: tolerância média → replicação assíncrona com cache.
Write locality — onde gravar
Em active-active, decidir onde gravar é escolha crítica. A pergunta: usuário na Europa escrevendo dado, vai para região europeia ou americana?
Local write (preferred). Escreve na região mais próxima. Latência baixa; melhor UX. Replicação para outras regiões em background. Conflicts possíveis se mesmo dado é escrito simultaneamente em duas regiões — necessita conflict resolution.
Home region write. Cada usuário/tenant tem "home region"; sempre escreve lá independente de localização. Sem conflicts (um escritor por dado); latência depende de quão próximo o usuário está da home region.
Forwarded write. Cliente escreve em região local; aplicação reencaminha para "leader" do dado. Latência alta (round-trip cliente → local → leader → local → cliente), mas consistency forte.
Quorum write. Cliente escreve em região local; aplicação coordena commit em majoritário cross-region. Spanner-style. Latência ~1 RTT cross-region; consistency strong.
Para a maioria dos casos, a escolha é entre Local (CRDT-friendly) e Home (sharded por user/tenant). Quórum global é apropriado apenas para sistemas financeiros ou similares onde consistency forte é mandatória.
Conflict resolution — quando dois lados escrevem
Em active-active local-write, conflicts são possíveis. Usuário em Europa edita perfil; ao mesmo tempo, mesma usuário (de outro device) edita perfil de US. Duas versões; qual vence?
Last-write-wins (LWW). Timestamp decide. Simples mas pode perder dados (uma das escritas é descartada). Requer clocks sincronizados (NTP suficiente para a maioria; Spanner usa TrueTime).
Vector clocks. Riak usa. Determina ordem causal entre escritas. Quando ordem causal não pode ser determinada (escritas concorrentes), retorna múltiplas versões ("siblings"); aplicação resolve.
CRDT. Tipos de dados que mesclam automaticamente sem conflict. G-Counter (cresce apenas), G-Set (adiciona apenas), OR-Set (add/remove com semântica clara), LWW-Register. Usado em Riak, Redis CRDT, Yjs (colaboração).
Aplicação resolve. Em sistemas complexos, conflict é exposto à aplicação que decide com regras de domínio. CouchDB faz isso. Trabalho extra, mas semântica clara.
A escolha depende da semântica. Email/perfil: LWW costuma ser ok. Saldo financeiro: nunca LWW (pode "perder" dinheiro); use CRDT counter ou single-leader. Inventory: depende — alguns domínios toleram conflict, outros não.
Failover regional — quando uma região cai
Multi-region precisa de plano para falha regional. RTO (Recovery Time Objective): quanto tempo até sistema voltar; RPO (Recovery Point Objective): quanto dado pode ser perdido.
Active-passive failover. Detecta falha da primária (health check); promove passive a primária; redireciona tráfego (DNS, load balancer). RTO: 30s a 5 min. RPO: lag de replicação no momento da falha (tipicamente segundos a minutos).
Active-active "drain". Detecta falha; tráfego é desviado para outras regiões (já operando). RTO: tempo de detecção (~30s). RPO: 0 (writes que estavam na região falhada replicaram para outras antes; a menos que falha tenha sido instantânea sem replicação).
Detecção: Route 53 health checks, Kubernetes Federation, custom probes. Cuidado com false positives (rede entre regiões temporária — conceito 07 cobriu split brain).
Redirecionamento: GeoDNS (mais simples), anycast routing (mais sofisticado), ou aplicação-level (cliente sabe múltiplas regiões).
Recovery: quando região volta, precisa sincronizar antes de aceitar tráfego. Pode levar tempo dependendo de quanto está atrás.
Times maduros testam failover regularmente — Netflix Chaos Monkey "Simian Army" tinha "Chaos Kong" que derrubava AWS regions. Sistema que nunca testou failover provavelmente falha no momento real.
CAP/PACELC em multi-region
O conceito 07 cobriu CAP. Em multi-region, o teorema fica especialmente concreto. Particionamento cross-region é evento real (mesmo que raro); cada região precisa decidir entre disponibilidade e consistência.
Sistemas CP cross-region (Spanner, CockroachDB). Quórum global. Em partição (uma região isolada), região minoritária fica indisponível para writes. Disponibilidade sacrificada para preservar consistência.
Sistemas AP cross-region (Cassandra, DynamoDB Global Tables). Cada região continua aceitando writes em partição. Conflicts resolvidos quando partição se cura. Disponibilidade preservada; consistency eventual.
Single-region primary com replicas remotas. Primary em uma região, replicas em outras. Em partição, primary continua se tem majority dos seus AZs; replicas remotas ficam read-only ou indisponíveis. Comportamento híbrido.
Em PACELC, sistemas multi-region elegem
explicitamente sua classificação. Spanner é
"PC/EC" mesmo cross-region (consistency sempre).
DynamoDB Global Tables é "PA/EL" (availability +
latency em modo normal). Cassandra com
LOCAL_QUORUM faz strong consistency
dentro da região, eventual cross-region — meio
termo configurável.
Latência percebida pelo usuário
Em multi-region, latência percebida tem duas componentes principais:
Cliente → região mais próxima. Idealmente baixa via geo-DNS ou anycast. Para usuário na Europa servido por região europeia: ~10-30 ms.
Round-trip cross-region (quando necessário). Para writes que precisam cross-region (quórum global), ou reads que precisam de consistency forte (cliente em Europa lendo de primary em US): 50-200 ms.
A diferença é dramática. Para minimizar latência cross-region, sistemas modernos:
- Localizam writes por usuário (home region) sempre que possível.
- Usam eventual consistency para reads onde tolerável.
- Cacheiam aggressivamente em CDN (módulo 06 conceito 10).
- Movem lógica para edge (Cloudflare Workers, CloudFront Functions).
- Aceitam que algumas operações pagam latência cross-region — e as escolhem deliberadamente.
Os bancos multi-region modernos
Conhecer o que cada banco oferece é parte do vocabulário.
Spanner (Google Cloud). Strong consistency global via TrueTime. Writes pagam ~1 RTT cross-region. Operação simples para o desenvolvedor (SQL); complexidade interna alta.
CockroachDB. Inspirado em Spanner. Roda fora de GCP. Strong consistency global; trade-off similar.
DynamoDB Global Tables. Active-active, eventual consistency. Last-write-wins por timestamp. Latência baixa local; consistency eventual cross-region.
Aurora Global Database. Aurora MySQL/Postgres com replicação cross-region assíncrona. Active-passive típico; failover automático. Lag tipicamente < 1 segundo.
Cassandra com multi-DC replication.
Tunable consistency cross-region.
LOCAL_QUORUM para strong dentro da
região; EACH_QUORUM para strong
cross-region (caro).
YugabyteDB. Postgres-compatible, distributed SQL. Multi-region nativo.
FoundationDB. Strict ACID multi-region. Apple usa em escala massiva.
A escolha depende de requirement de consistency vs latência. Strong consistency global é cara em latência; eventual consistency permite latência baixa mas semântica mais difícil.
Multi-region em três stacks
Configurar multi-region varia por stack.
// Cosmos DB tem multi-region nativo (multi-write opcional)
var cosmosClient = new CosmosClient(connectionString, new CosmosClientOptions
{
ApplicationPreferredRegions = new[] { "Brazil South", "East US", "West Europe" },
// ordem de preferência; cliente vai à primeira região acessível
ConsistencyLevel = ConsistencyLevel.Session, // session consistency
// outras opções: Strong, BoundedStaleness, Eventual, ConsistentPrefix
});
// reads vão para região mais próxima automaticamente
var pedido = await container.ReadItemAsync<Pedido>(id, partitionKey);
// writes:
// - single-write region: vai para primary
// - multi-write region: vai para region local (eventual cross-region)
await container.UpsertItemAsync(pedido, partitionKey);
// para Postgres com Aurora Global Database, usar dois connection strings:
// primary write: cluster-rw.aws.amazonaws.com (US-East)
// reader local: cluster-ro.eu-west-1.rds.amazonaws.com (Europe)
// failover automático via DNS quando primary cai
Cosmos DB é o exemplo mais ergonômico em .NET de multi-region. Configurações de consistency escolhidas explicitamente. Para Aurora ou outros, configuração mais manual.
import boto3
from boto3.dynamodb.conditions import Key
# DynamoDB Global Tables: replicação automática cross-region
# (configurada via AWS console / Terraform)
# cliente conecta em região mais próxima
session = boto3.Session(region_name="sa-east-1") # Brazil
table = session.resource("dynamodb").Table("Pedidos")
# write — vai para região local automaticamente
table.put_item(Item={
"tenant_id": tenant_id,
"pedido_id": pedido_id,
"valor": 100.0,
})
# read — também região local; eventual consistency
response = table.get_item(
Key={"tenant_id": tenant_id, "pedido_id": pedido_id},
# ConsistentRead=True para strong dentro da região,
# mas não cross-region (Global Tables são sempre eventual cross-region)
)
# para detectar conflicts (LWW), considerar campo "version"
# ou usar Streams para auditoria de updates
# alternativa: aplicação multi-region tradicional com tenant home region
# routing baseado em DynamoDB que armazena home region por tenant
home_region = get_home_region(tenant_id)
writer = boto3.Session(region_name=home_region).resource("dynamodb").Table("Pedidos")
writer.put_item(...) # write sempre na home region
DynamoDB Global Tables abstrai replicação cross-region. Aplicação interage com tabela local; AWS replica em background. Comportamento eventual cross-region por design.
package main
import (
"github.com/gocql/gocql"
)
// configuração com nodes em duas regiões
cluster := gocql.NewCluster(
"cassandra-us-east-1.example.com",
"cassandra-us-east-2.example.com",
"cassandra-eu-west-1.example.com",
"cassandra-eu-west-2.example.com",
)
cluster.Keyspace = "app"
// LOCAL_QUORUM: majoritário dentro da região local
// para writes que toleram eventual cross-region
cluster.Consistency = gocql.LocalQuorum
// HostFilter para routing local (region-aware)
cluster.HostFilter = gocql.DataCentreHostFilter("us-east-1")
session, _ := cluster.CreateSession()
defer session.Close()
// write com LOCAL_QUORUM: rápido, eventual cross-region
err := session.Query(
`INSERT INTO pedidos (tenant_id, pedido_id, valor) VALUES (?, ?, ?)`,
tenantID, pedidoID, valor,
).Exec()
// para writes que precisam de strong cross-region:
err = session.Query(`...`).Consistency(gocql.EachQuorum).Exec()
// EACH_QUORUM: majoritário em CADA região; muito caro em latência
// schema: replicação configurada por keyspace
// CREATE KEYSPACE app WITH REPLICATION = {
// 'class': 'NetworkTopologyStrategy',
// 'us-east-1': 3,
// 'eu-west-1': 3
// };
Cassandra é exemplo canônico de multi-region
tunable. LOCAL_QUORUM para
performance; EACH_QUORUM para
consistency global. Aplicação escolhe por
query.
Anti-padrões frequentes
Multi-region sem articular consistency. Time adota multi-region porque "é melhor"; depois descobre que feature crítica precisa strong consistency e o sistema não entrega. Defesa: articular requirements de consistency antes de escolher arquitetura.
Single-region escondido em multi-region. Sistema declara multi-region mas todas as escritas vão para uma região (single-write). Em failure dessa região, sistema fica fora apesar de ter "multi-region". Defesa: articular se é active-passive conscientemente, ou planejar para active-active.
Failover não testado. Sistema tem multi-region, mas time nunca derrubou região em staging. Quando primary cai em produção, failover não funciona como esperado. Defesa: chaos engineering — derrubar regiões em staging regularmente.
Latência cross-region em loop. Aplicação faz N queries, cada uma cross-region. N × 100 ms = latência inaceitável. Defesa: batch; ou rotear para local; ou aceitar que essa operação é cross-region cara.
Compliance esquecida. Multi-region adicionado, mas dados europeus replicam para US. GDPR violation. Defesa: articular soberania de dados antes de configurar replicação; shard geográfico onde necessário.
Cost surprises. Egress de dados cross-region é caro em cloud (~$0.02/GB típico). Replicação contínua de dataset grande pode gerar fatura inesperada. Defesa: estimar custo de egress no design; comprimir; replicar seletivamente.
Split brain regional não detectado. Rede entre regiões particiona; cada lado pensa que é o único disponível; ambos aceitam writes; eventualmente partição se cura; conflicts massivos (alguns dados duplicados, alguns escritos divergentes). Sistema sem detecção de split brain pode operar em estado inconsistente por horas. Defesa: leader election baseado em consenso (etcd, ZooKeeper) que requer majoritário; ou banco com majority quorum nativo (Spanner, CockroachDB) que recusa writes sem majoritário; testes de chaos que simulam partições reais.
Antes de adotar multi-region, articule cinco coisas. "SLA target — multi-region é necessário?". "Latência percebida — usuários globais com SLO agressivo?". "Compliance — soberania de dados aplicável?". "Consistency requirements por feature — strong, eventual, ou ambos?". "Time tem expertise para operar sistema distribuído cross-region?". Sistemas que partem para multi-region sem essas cinco respostas tipicamente acumulam complexidade sem ganho. Sistemas que respondem antes constroem com ergonomia adequada.
Por que importa para a sua carreira
Multi-region aparece em sistemas críticos e em empresas globais. Em entrevistas para vagas em empresas com presença global (FAANG, fintech internacional, plataformas de mensageria), "como você desenharia para SLA 99.999% global?" é pergunta direta — a resposta forte cita active-active vs active-passive, consistency models cross-region, write locality, conflict resolution. Em revisão de proposta, identificar multi-region prematuro é serviço (a maioria dos sistemas não precisa). Em pos-mortem de outage regional, articular como multi-region teria mitigado é trabalho de senior. Em discussão de compliance, articular geographic distribution como ferramenta para soberania é vocabulário maduro.
Como praticar
- DynamoDB Global Tables hands-on. Crie tabela global com 2 regiões (custos modestos para experimentos). Escreva em uma região; meça quanto tempo leva para aparecer na outra. Force conflict (escrever simultaneamente em duas regiões); observe LWW resolution. Esse exercício torna concreto o trade-off eventual.
- Aurora Global Database failover. Crie Aurora cluster com global database (primary + secondary region). Em staging, force failover (manual ou via API). Meça RTO. Verifique data loss (RPO). Esse teste é o que sêniores fazem antes de confiar em multi-region em produção.
- Análise de arquitetura existente. Pegue um sistema seu (ou aberto) com pretensão global. Articule: é single-region ou multi-region? Active-passive ou active-active? Quais bancos? Consistency model? Identifique pelo menos um gap (compliance, latência, failover não testado) e proponha mitigação. Esse é exercício arquitetural valioso.
Referências para aprofundar
- paper Spanner: Google's Globally-Distributed Database — Corbett et al., Google (OSDI, 2012).
- paper Dynamo: Amazon's Highly Available Key-value Store — DeCandia et al., Amazon (SOSP, 2007).
- livro Designing Data-Intensive Applications — Martin Kleppmann (O'Reilly, 2017).
- livro Database Internals — Alex Petrov (O'Reilly, 2019).
- livro Site Reliability Engineering — Beyer et al., Google (O'Reilly, 2016).
- artigo AWS Multi-Region Application Architecture — AWS Whitepaper.
- artigo Building a Global SaaS Application — Various AWS posts.
- docs DynamoDB Global Tables.
- docs Aurora Global Database.
- docs Cosmos DB Multi-Master.
- docs CockroachDB Multi-Region.
- vídeo Architecting for Geographic Distribution — várias palestras de AWS re:Invent (2020+).