Scaling
Escopo: transversal. Aplica-se a qualquer linguagem ou stack do projeto.
Escalar um sistema é resolver um problema de capacidade: mais tráfego, mais dados, mais usuários simultâneos. A armadilha é investir em infraestrutura para um problema que ainda não existe. A postura correta: construir com base sólida e escalar quando os dados indicarem necessidade.
Conceitos fundamentais
| Conceito | O que é |
|---|---|
| Vertical scaling (escala vertical) | Aumentar CPU, RAM ou disco da máquina existente |
| Horizontal scaling (escala horizontal) | Adicionar mais instâncias da aplicação atrás de um balanceador |
| Stateless (sem estado local) | Aplicação que não guarda estado em memória entre requisições; pode ser replicada sem coordenação |
| Load Balancer (balanceador de carga) | Componente que distribui requisições entre múltiplas instâncias da aplicação |
| API Gateway (gateway de API) | Ponto de entrada único que centraliza autenticação, roteamento, rate limiting e logging |
| CDN (Content Delivery Network · Rede de Distribuição de Conteúdo) | Rede de servidores geograficamente distribuídos que serve assets estáticos próximo ao usuário |
| Rate limiting (limitação de taxa) | Controle do número de requisições aceitas por cliente em um intervalo de tempo |
| SSL termination (encerramento de SSL) | Descriptografia do tráfego HTTPS no balanceador, aliviando as instâncias da aplicação |
| Health check (verificação de saúde) | Endpoint que o balanceador consulta para saber se uma instância está saudável |
| Read replica (réplica de leitura) | Cópia do banco sincronizada com a primária, usada exclusivamente para leitura |
| Sticky session (sessão fixada) | Redirecionar sempre o mesmo usuário para a mesma instância; necessário em apps com estado local |
Escala vertical
Aumentar a capacidade da máquina: mais CPU (Central Processing Unit · Unidade Central de Processamento), mais RAM (Random Access Memory · Memória de Acesso Aleatório), disco mais rápido.
Vantagens: zero mudança de código e zero complexidade de infraestrutura. Resolve a maioria dos gargalos de um sistema em crescimento.
Limite: existe um teto físico e financeiro. Uma máquina maior sempre custa mais do que duas máquinas menores com a mesma capacidade somada.
Quando usar: como primeiro passo de qualquer escala. Meça, identifique o gargalo, aumente o recurso correspondente. Passe para a escala horizontal quando o teto vertical for atingido ou quando o custo se tornar proibitivo.
Escala horizontal
Adicionar mais instâncias da aplicação e distribuir a carga entre elas.
Requisito central: a aplicação precisa ser stateless (sem estado local). Estado em memória (sessão, cache local, WebSocket com estado) impede a replicação, porque cada requisição precisa poder cair em qualquer instância e produzir o mesmo resultado.
Como tornar a aplicação stateless:
| Estado | Onde mover |
|---|---|
| Sessão de usuário | Redis, banco de dados ou JWT (token autocontido) |
| Cache local | Redis ou Memcached compartilhado |
| Arquivos temporários | Object storage (S3, Blob Storage) |
| Filas em memória | Message broker (RabbitMQ, SQS, Kafka) |
Com a aplicação stateless, adicionar instâncias tem efeito linear: duas instâncias dobram a capacidade, dez multiplicam por dez.
Balanceamento de carga
O Load Balancer (balanceador de carga) distribui as requisições entre as instâncias disponíveis, e é o ponto de entrada da escala horizontal.
Algoritmos de distribuição
| Algoritmo | Como funciona | Melhor para |
|---|---|---|
| Round Robin (rotação sequencial) | Distribui em ordem circular entre as instâncias | Requisições com tempo de resposta similar |
| Least Connections (menor número de conexões) | Direciona para a instância com menos conexões ativas | Requisições com tempo de resposta variável |
| IP Hash (hash do IP do cliente) | Sempre direciona o mesmo IP para a mesma instância | Apps que ainda têm estado local (sticky session) |
| Weighted (ponderado) | Distribui proporcionalmente à capacidade de cada instância | Instâncias com capacidades diferentes |
Health checks
O balanceador consulta periodicamente um endpoint de cada instância (GET /health) e remove da rotação as que não respondem ou respondem com erro, até que se recuperem.
Load Balancer → GET /health → 200 OK → instância saudável, recebe tráfego
Load Balancer → GET /health → timeout → instância removida da rotação
SSL termination
O balanceador recebe o tráfego HTTPS (HyperText Transfer Protocol Secure · Protocolo Seguro de Transferência de Hipertexto), descriptografa e repassa HTTP (HyperText Transfer Protocol · Protocolo de Transferência de Hipertexto) simples para as instâncias internas. O gerenciamento de certificados fica centralizado no balanceador.
Cliente → HTTPS → Load Balancer (SSL termination) → HTTP → Instâncias
API Gateway
O API Gateway é o ponto de entrada único para todos os serviços de uma API (Application Programming Interface · Interface de Programação de Aplicações). Ele centraliza responsabilidades que, sem ele, teriam de ser implementadas em cada serviço.
Responsabilidades centrais:
| Responsabilidade | O que faz |
|---|---|
| Autenticação | Valida tokens antes de chegar aos serviços; serviços recebem identidade já verificada |
| Rate limiting | Limita requisições por cliente, IP ou rota; protege os serviços de abuso |
| Roteamento | Direciona /orders/* para o serviço de pedidos, /users/* para o serviço de usuários |
| SSL termination | Gerencia certificados HTTPS centralmente |
| Logging e observabilidade | Registra todas as requisições em um único ponto; correlação de traces |
| Transformação de payload | Adapta formatos entre clientes e serviços quando necessário |
Cliente → API Gateway → autenticação → rate check → roteamento → Serviço A | Serviço B
O API Gateway é infraestrutura de entrada: faz pré-processamento e roteamento, e deixa a lógica de negócio para os serviços.
Ferramentas comuns: AWS API Gateway, Kong, Nginx, Traefik, Caddy.
Estratégias para escalar
Além de instâncias e balanceadores, existem camadas de escala que dispensam servidores novos:
CDN para assets estáticos: imagens, JS, CSS e fontes servidos a partir de nós geograficamente próximos ao usuário, sem carga nenhuma no servidor de aplicação.
Cache na borda: respostas de API guardadas no Redis ou Memcached, de modo que as requisições repetidas param antes de chegar ao banco.
Requisição → Cache hit → resposta em < 1ms
Requisição → Cache miss → banco → armazena → resposta
Read replicas: em sistemas com muito mais leitura do que escrita, as réplicas de leitura absorvem as queries SELECT sem tocar na instância primária.
Escrita → banco primário
Leitura → read replica 1 | read replica 2 | read replica N
Filas para absorver picos: em vez de processar operações lentas de forma síncrona, enfileire e processe em background. O servidor de aplicação responde rápido e o worker (processo que executa tarefas em segundo plano) absorve o pico no seu próprio ritmo.
Evitar engenharia excessiva
A maioria dos projetos nunca vai precisar de escala horizontal, balanceador dedicado ou várias read replicas. Investir nessa infraestrutura antes de ter o problema custa complexidade e não entrega nada em troca.
Sequência correta:
1. Monolito Modular + escala vertical
2. Otimizar queries e adicionar cache quando os dados indicarem
3. Adicionar load balancer e tornar stateless quando o tráfego exigir
4. Considerar read replicas quando leitura virar gargalo no banco
5. Microsserviços apenas quando limites de domínio ou times impuserem isolamento real
Cada etapa só faz sentido depois que a anterior se esgotou. Pular etapas aumenta a complexidade sem benefício proporcional.
Sinais de que é hora de escalar:
| Sinal | Ação correspondente |
|---|---|
| CPU ou memória consistentemente acima de 70% | Escala vertical primeiro |
| Tempo de resposta crescendo com o volume | Revisar queries e adicionar cache |
| Máquina maior não resolve mais | Avaliar escala horizontal |
| Um módulo tem tráfego radicalmente diferente dos demais | Considerar extração cirúrgica |
O que evitar no início:
- Configurar load balancer antes de ter tráfego que justifique
- Separar em microsserviços porque "vai crescer"
- Montar Kubernetes para uma aplicação com 10 usuários simultâneos
- Implementar CQRS (Command Query Responsibility Segregation · Separação de Responsabilidade entre Comando e Consulta) e event sourcing sem uma complexidade de leitura e escrita que justifique
Referência rápida
| Técnica | Quando usar | Custo de adoção |
|---|---|---|
| Escala vertical | Primeiro passo sempre | Nenhum (sem mudança de código) |
| Cache (Redis) | Leitura frequente, escrita infrequente | Baixo (lib + Redis) |
| CDN | Assets estáticos com usuários distribuídos | Baixo (configuração de DNS) |
| Load Balancer | Tráfego que uma instância não absorve | Médio (app deve ser stateless) |
| Read Replica | Leitura virou gargalo no banco | Médio (configuração de banco) |
| API Gateway | Múltiplos serviços ou autenticação centralizada | Médio (configuração e routing) |
| Microsserviços | Isolamento real por domínio ou time | Alto (complexidade operacional) |
DoDocs v3.7.0 · Desenvolvido por @thiagocajadev · Baseado no trabalho de pmndrs/docs · Poimandres.