MÓDULO 07 · CONCEITO 11 DE 12

Multi-region e geographic distribution

Active-passive, active-active, write locality, latência cross-region, eventual consistency entre regiões. Failover regional. A última camada de escala — onde física da velocidade da luz vira restrição arquitetural.

Tempo de leitura ~22 min Pré-requisito Conceitos 05, 06 e 07 (replicação, sharding, CAP) Próximo CQRS e read-models

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:

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.

C# — ASP.NET Core com Cosmos DB multi-region
// 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.

Python — DynamoDB Global Tables com boto3
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.

Go — Cassandra multi-DC com tunable consistency
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.

armadilha em produção

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.

heurística do sênior

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

  1. 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.
  2. 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.
  3. 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

  1. paper Spanner: Google's Globally-Distributed Database — Corbett et al., Google (OSDI, 2012). research.google/pubs/pub39966 — Paper canônico de banco multi-region com strong consistency. Indispensável.
  2. paper Dynamo: Amazon's Highly Available Key-value Store — DeCandia et al., Amazon (SOSP, 2007). Multi-region eventual consistency. Já citado em conceito 04. Conexão direta com DynamoDB Global Tables.
  3. livro Designing Data-Intensive Applications — Martin Kleppmann (O'Reilly, 2017). Cap. 5 e 9 cobrem replication e consistency cross-region em profundidade. Indispensável.
  4. livro Database Internals — Alex Petrov (O'Reilly, 2019). Cap. 13-15 sobre distributed databases incluindo multi-region. Cobertura técnica de protocolos.
  5. livro Site Reliability Engineering — Beyer et al., Google (O'Reilly, 2016). Cap. 26 (Data Integrity) inclui geographic redundancy. Gratuito.
  6. artigo AWS Multi-Region Application Architecture — AWS Whitepaper. aws.amazon.com/architecture/global-infrastructure — Padrões oficiais de AWS para multi-region.
  7. artigo Building a Global SaaS Application — Various AWS posts. aws.amazon.com/blogs/architecture — Casos práticos de SaaS multi-region em AWS.
  8. docs DynamoDB Global Tables. docs.aws.amazon.com/amazondynamodb/latest/developerguide/GlobalTables.html — Documentação oficial. Eventual consistency, conflict resolution explícita.
  9. docs Aurora Global Database. docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-global-database.html — Postgres/MySQL multi-region. RPO/RTO documentados.
  10. docs Cosmos DB Multi-Master. learn.microsoft.com/en-us/azure/cosmos-db/distribute-data-globally — Microsoft Cosmos DB com multi-region. Consistency levels documentados.
  11. docs CockroachDB Multi-Region. cockroachlabs.com/docs/stable/multiregion-overview — Como CockroachDB faz multi-region SQL com strong consistency.
  12. vídeo Architecting for Geographic Distribution — várias palestras de AWS re:Invent (2020+). YouTube. AWS publica anualmente sessões sobre multi-region. Vale procurar pelas mais recentes.