MÓDULO 07 · 2 SEMANAS · ESCALABILIDADE

Escalabilidade — de 100 a 100M sem reescrever

Stateless services, consistent hashing, sharding, CAP, autoscaling, multi-tenancy, multi-region. A diferença entre sistema que cresce com o tráfego e sistema que precisa ser reescrito a cada ordem de magnitude.

Duração ~2 semanas
Conceitos 12 fundamentais
Projeto Notificações async escaláveis
Pré-requisito Módulos 03, 04, 05, 06
Escalabilidade Custo Disponibilidade

Doze conceitos para entender escalabilidade como propriedade arquitetural — não como mágica de deploy. Da escolha de scale up vs scale out aos limites fundamentais (CAP, PACELC), das primitivas que habilitam horizontalidade (stateless, consistent hashing, sharding) aos padrões de produção (autoscaling, multi-tenancy, multi-region, CQRS). O fio condutor é uma pergunta única: como construir sistema que cresce 100× sem reescrever 100% do código?

01

Vertical vs horizontal — scale up vs scale out

Custos relativos, limites físicos do scale up, por que horizontal venceu em web, quando vertical ainda ganha (banco, cache em casos específicos).

estudar →
02

Stateless é o que escala

Externalizar estado (banco, Redis, S3), sticky sessions vs sessions distribuídas. Por que microsserviço com estado em memória é dívida arquitetural.

estudar →
03

Load balancing

Algoritmos (round-robin, least connections, weighted, IP hash), L4 vs L7, health checks, connection draining em deploy. Da NGINX à Envoy.

estudar →
04

Consistent hashing

David Karger et al. (STOC, 1997). Virtual nodes, anel de hash. A base de Cassandra, DynamoDB, e CDN — o porquê de a maioria dos sistemas distribuídos modernos não particionarem por id mod N.

estudar →
05

Replicação para escala de leitura

Primary/replica, replication lag, read-your-writes, replica selection. Complemento prático ao módulo 03 (mecânica) e ao módulo 06 conceito 11 (uso aplicacional).

estudar →
06

Sharding e particionamento

Estratégias (range, hash, geo, tenant), hot shards, rebalanceamento, resharding online. Por que sharding é decisão de design irreversível e como mitigar.

estudar →
07

CAP, PACELC e os limites fundamentais

Eric Brewer (PODC, 2000), prova de Lynch & Gilbert (2002), PACELC de Daniel Abadi (2010). Implicações práticas para escolha de banco distribuído.

estudar →
08

Auto-scaling

HPA (Kubernetes), AWS Auto Scaling Groups, métricas de scaling (CPU, RPS, queue depth), reactive vs predictive. Por que scale-down é mais difícil que scale-up.

estudar →
09

Backpressure e elastic systems

Reactive Manifesto, quando absorver carga vs rejeitar, queue depth como sinal, graceful degradation. Conexão com módulo 04 conceito 12 (backpressure local).

estudar →
10

Multi-tenancy

Silo (DB por tenant), pool (DB compartilhado), hybrid (bridge model). Noisy neighbor, tenant isolation, billing implications, compliance.

estudar →
11

Multi-region e geographic distribution

Active-passive, active-active, write locality, latência cross-region, eventual consistency entre regiões. Failover regional.

estudar →
12

CQRS e read-models — escalando leitura desacoplada da escrita

Greg Young (2010), comando/query separados, projeções, event sourcing como base. Quando vale a complicação e quando é overkill.

estudar →
princípio orientador

Escalabilidade não é mágica de cloud — é propriedade que se desenha desde o primeiro commit. Sistemas escalam quando: o estado mora fora do processo (banco, cache, fila); o roteamento é estável sob mudança de capacidade (consistent hashing); a partição não cria hot shards; a replicação resolve leitura sem sacrificar consistência inadequadamente; e o time articula CAP/PACELC como restrição, não surpresa. O senior aprende a olhar o sistema com dois eixos simultâneos: como ele responde hoje (latência, throughput) e como ele responderia se o tráfego crescesse 10×. A diferença entre os dois eixos define quanto tempo de vida ele tem antes de virar reescrita.

Escalabilidade está cheia de regras populares ("é só adicionar máquina", "Kubernetes resolve") que mais atrapalham do que ajudam. Cada decisão abaixo é confronto direto com uma dessas regras — e a resposta saudável quase sempre depende do tipo de carga e da topologia do sistema.

Vertical ou horizontal?

Para serviços de aplicação stateless (web, API), horizontal sempre. Custo linear, capacidade ilimitada na prática, falha de uma instância não derruba o sistema. Para banco e cache, vertical primeiro até o limite — uma máquina grande é mais simples de operar que cluster distribuído, e a complexidade de sharding é cara. AWS RDS suporta instâncias com 96 cores e terabytes de RAM em 2026; PostgreSQL nessa máquina aguenta carga que muitos times não atingem. A regra prática: scale up até começar a doer, depois scale out.

Sharding agora ou depois?

Quase sempre depois. Sharding é decisão de design irreversível ou cara de reverter — uma vez que dados estão particionados por tenant_id, queries cross-tenant ficam complicadas; uma vez por user_id, relatórios agregados ficam pesados. Adiar até que vertical + replicação não bastem é geralmente saudável. Quando chegar a hora, preferir consistent hashing a id mod N; preferir tenant-based a hash-based em multi-tenancy; sempre prever resharding desde o início (mesmo que ainda não tenha sido necessário).

Multi-region desde o início?

Raramente. Multi-region adiciona complexidade qualitativa — replicação cross-region, write locality, latência aumentada, eventual consistency, custo maior. Para a maioria dos sistemas que servem um país, single-region com múltiplas AZs é suficiente para SLA de 99.99%. Multi-region só vale quando: usuários geograficamente distribuídos com SLO agressivo de latência (< 100 ms global); requisito regulatório de soberania de dados; SLA de 99.999% com redundância regional. Para sistemas que crescem rápido, deixar multi-region como "v2" é frequentemente decisão correta.

Auto-scaling reativo ou preditivo?

Reativo (baseado em métrica corrente) é o default saudável para a maioria dos sistemas. Simples, confiável, ajusta a tráfego real. Limitação: tem atraso (alguns minutos para scale up). Sistemas com picos previsíveis e abruptos (Black Friday, lançamento de produto, Olimpíadas) ganham com preditivo — escalonar baseado em previsão antes do pico chegar. AWS Auto Scaling tem Predictive Scaling; Kubernetes KEDA tem cron-based. Combinar os dois (preditivo para picos previsíveis, reativo para o resto) é o padrão maduro.

CQRS desde o início ou só quando precisar?

Só quando precisar. CQRS adiciona complexidade qualitativa: dois modelos, sincronização eventual, projeções para manter. Em sistemas jovens, complica desproporcionalmente. CQRS ganha tração quando: read scale >> write scale (típico em e-commerce, mídia); modelos de leitura naturalmente diferentes do modelo de escrita; necessidade de múltiplas projeções (busca, analytics, dashboard). Mesmo então, começar com CQRS "leve" (read replica + queries distintas) antes de adotar event sourcing completo é caminho mais sustentável.

O projeto força a sentir cada conceito do módulo em um sistema realista — pipeline de notificações async (email, push, SMS) que precisa absorver picos (campanhas, eventos), distribuir trabalho entre muitos workers, e garantir que ninguém fica sem notificação durante autoscaling.

PROJETO PRÁTICO

Pipeline de notificações async escalonável

API que recebe pedidos de notificação (de outros serviços ou jobs), enfileira em fila distribuída sharded por user_id via consistent hashing, e processa via pool de workers stateless que podem escalonar horizontalmente. Provedores externos (SES, SNS, FCM) são consumidos com retry/circuit breaker. O sistema deve absorver picos de 100× sem perder notificações nem violar ordem de entrega por usuário.

REQUISITOS
  • API REST que aceita batch de notificações com idempotency key
  • Fila distribuída (Kafka, RabbitMQ, ou SQS) com partição por user_id
  • Workers stateless que processam fila e despacham para provedores externos
  • Retry/circuit breaker em chamadas a provedores (Polly/tenacity/gobreaker)
  • Auto-scaling de workers baseado em queue depth (KEDA ou equivalente)
  • Métricas: throughput, latência fim-a-fim por canal, taxa de falha por provedor
  • Multi-tenant com isolation: noisy neighbor não atrapalha outros tenants
  • Idempotência ponta-a-ponta: receber a mesma notificação 2× não envia 2×
  • Ordem de entrega por usuário preservada (notificação 1 chega antes da 2)
  • Spike test que aumenta carga 100× e valida que sistema escala sem perda
  • Soak test 24h validando que sistema sustenta carga sem vazamento
  • Failover de região simulado: 1 região fora, sistema continua sem perder notificações enfileiradas
Escalabilidade Custo Disponibilidade
STACK SUGERIDA POR LINGUAGEM
STACK
.NET 10 + ASP.NET Core Minimal API + MassTransit (RabbitMQ) ou Confluent.Kafka + EF Core (Postgres) + Polly + KEDA + Pyroscope.NET + k6 + AWS SES/SNS
ESTRUTURA / NOTAS
  • Notifications.Api/ com endpoint POST que valida idempotency
  • Notifications.Workers/ com consumer escalonável via KEDA
  • Notifications.Domain/ com aggregate Notification e regras de retry
  • Notifications.Infra/ com adapters para SES/SNS/FCM com Polly
  • Postgres com tabela particionada por hash de tenant_id
  • Kafka com 32 partitions e key=user_id (ordem garantida por user)
  • k6 com cenário de spike (1× → 100×) e soak (24h)
STACK
Python 3.13 + FastAPI + Celery (com RabbitMQ ou Redis) ou faust-streaming (Kafka) + SQLAlchemy 2 + tenacity + KEDA + Pyroscope-Python + k6 + AWS boto3
ESTRUTURA / NOTAS
  • notifications/api/ com endpoint async
  • notifications/workers/ com Celery ou faust agents stateless
  • notifications/domain/ com dataclasses imutáveis
  • notifications/adapters/ com clients SES/SNS/FCM e tenacity
  • Postgres com partitioning by hash; tabela outbox para garantir at-least-once publish
  • Kafka com 32 partitions, key=user_id
  • locust ou k6 para spike e soak
STACK
Go 1.23 + chi + segmentio/kafka-go ou IBM/sarama + pgx + sony/gobreaker + KEDA + grafana-pyroscope-go + k6 + aws-sdk-go-v2
ESTRUTURA / NOTAS
  • cmd/api/ — endpoint HTTP minimal
  • cmd/worker/ — consumer Kafka escalonável
  • internal/domain/ — invariantes de Notification
  • internal/adapter/ — providers + breaker
  • Postgres com partitioning declarativo
  • Kafka segmentio com partition por user_id (FNV hash)
  • k6 spike + soak; correlação via OTel
entregável

Repositório com README documentando: o diagrama do pipeline (API → fila → workers → providers), o gráfico de throughput sob spike de 100× com autoscaling em ação, o soak de 24h provando estabilidade, o failover regional simulado (1 região fora) com mensagens em fila preservadas, o ADR justificando escolha de fila e particionamento, e um teste de regressão que prova ordem de entrega por usuário sob alta concorrência. Bonus: gráfico de custo por mil notificações em diferentes níveis de carga (mostra que custo escala sublinearmente).

Escalabilidade é tópico canônico em entrevistas de senior, especialmente para vagas em sistemas com crescimento. As perguntas abaixo cobrem a faixa que diferencia quem entende deploy de quem entende topologia.

Q.01

Diferença entre vertical e horizontal scaling, com um exemplo onde cada um ganha. Em que ponto você migraria de vertical para horizontal?

Q.02

Você precisa cachear dados em uma frota de 50 servidores. Por que não usaria id mod 50? Explique consistent hashing e por que ele venceu.

Q.03

Explique o teorema CAP. Em uma partição de rede, qual escolha um banco como Cassandra faz? E PostgreSQL? Por quê?

Q.04

Sistema atende SaaS multi-tenant. Cliente de tier free abusa e degrada experiência de tier enterprise. Como você previne (não resolve depois) esse cenário?

Q.05

Pipeline de notificações precisa preservar ordem por usuário e ser idempotente. Como você desenharia? Articule decisões de fila, particionamento, e idempotency.