System Design/02 - Componentes/Load Balancers2 min
Horizontal Scaling
- Que problema isso resolve?
- Quando usar / quando NÃO usar?
- Qual o principal trade-off?
- Como isso falha em produção?
Conceito
Adicionar mais máquinas em vez de máquinas maiores.
| Vertical (scale up) | Horizontal (scale out) | |
|---|---|---|
| Como | Máquina maior | Mais máquinas |
| Limite | Teto físico do hardware | Praticamente ilimitado |
| Custo | Cresce super-linearmente | Cresce ~linearmente |
| Disponibilidade | SPOF | Tolera falha de nó |
| Complexidade | Baixa | Alta |
| Downtime para escalar | Normalmente sim | Não |
O pré-requisito: stateless
Escalar horizontalmente só funciona se qualquer instância puder atender qualquer requisição. Isso exige tirar o estado de dentro do processo:
| Estado | Onde deveria estar |
|---|---|
| Sessão de usuário | Cache compartilhado, banco, ou token assinado (JWT) |
| Upload temporário | Armazenamento de objetos |
| Cache local | Cache distribuído (ou aceite duplicação) |
| Contador em memória | Banco ou Redis |
A alternativa — sticky session, prender o usuário a uma instância — funciona e reintroduz o problema: a instância morre e a sessão vai junto, e a distribuição de carga fica desigual.
Trade-offs
O ganho é capacidade elástica e tolerância a falha. O custo é toda a complexidade de sistemas distribuídos: coordenação, consistência, descoberta de serviço, observabilidade espalhada.
Dois limites teóricos merecem atenção:
- Lei de Amdahl: se 10% do trabalho é serial, nenhum paralelismo passa de 10x.
- Universal Scalability Law: além de certo ponto, adicionar nós piora o desempenho — o custo de coordenação entre eles cresce mais rápido que a capacidade adicionada.
Na prática, o gargalo raramente é a camada de aplicação. Adicionar servidores web funciona até todos disputarem o mesmo banco; aí o problema migra, e a solução deixa de ser "mais instâncias" e passa a ser Replication, Caching ou Sharding.
Escalar vertical primeiro costuma ser a decisão certa: é barato, imediato e adia complexidade real. O erro é tratá-lo como estratégia permanente.
Exemplo prático
Uma API a 70% de CPU com 4 instâncias. Sobem para 8 — e a latência não melhora.
O motivo: o gargalo migrou para o banco, que agora recebe o dobro de conexões. As 8 instâncias esperam I/O em vez de usar CPU.
A correção não é escalar mais a aplicação, é atacar onde o gargalo está: réplicas de leitura, pool de conexões, ou cache na frente do banco. Escalar a camada errada custa dinheiro e não entrega nada — e só a medição diz qual é a camada certa.
Relacionado
Parte de Load Balancers · roadmap.sh/system-design