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 é tentar resolver antecipadamente um problema que ainda não existe. A postura correta: construir com base sólida, escalar quando os dados indicarem necessidade.

Conceitos fundamentais

ConceitoO 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, zero complexidade de infraestrutura. Resolve a maioria dos gargalos de um sistema em crescimento.

Limite: tem teto físico e financeiro. Uma máquina maior sempre custa mais do que duas máquinas menores com a mesma capacidade total.

Quando usar: primeiro passo de qualquer escala. Medir, identificar o gargalo, aumentar o recurso correspondente. Só partir para escala horizontal quando o teto vertical for atingido ou 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 deve ser stateless (sem estado local). Estado em memória (sessão, cache local, WebSocket com estado) impede a replicação. Cada requisição deve poder cair em qualquer instância sem diferença de resultado.

Como tornar a aplicação stateless:

EstadoOnde mover
Sessão de usuárioRedis, banco de dados ou JWT (token autocontido)
Cache localRedis ou Memcached compartilhado
Arquivos temporáriosObject storage (S3, Blob Storage)
Filas em memóriaMessage broker (RabbitMQ, SQS, Kafka)

Com a aplicação stateless, adicionar instâncias é linear: duas instâncias dobram a capacidade, dez instâncias multiplicam por dez.

Load Balancing (Balanceamento de Carga)

O Load Balancer (balanceador de carga) distribui requisições entre as instâncias disponíveis. É o ponto de entrada da escala horizontal.

Algoritmos de distribuição

AlgoritmoComo funcionaMelhor para
Round Robin (rotação sequencial)Distribui em ordem circular entre as instânciasRequisições com tempo de resposta similar
Least Connections (menor número de conexões)Direciona para a instância com menos conexões ativasRequisições com tempo de resposta variável
IP Hash (hash do IP do cliente)Sempre direciona o mesmo IP para a mesma instânciaApps que ainda têm estado local (sticky session)
Weighted (ponderado)Distribui proporcionalmente à capacidade de cada instânciaInstâncias com capacidades diferentes

Health checks

O balanceador consulta periodicamente um endpoint de cada instância (GET /health). Instâncias que não respondem ou respondem com erro são removidas da rotação automaticamente até se recuperar.

Load BalancerGET /health → 200 OK → instância saudável, recebe tráfego
Load BalancerGET /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. As instâncias não precisam gerenciar certificados; o balanceador centraliza isso.

ClienteHTTPSLoad Balancer (SSL termination)HTTPInstâncias

API Gateway

O API (Application Programming Interface, Interface de Programação de Aplicações) Gateway é o ponto de entrada único para todos os serviços de uma API. Centraliza responsabilidades que, sem ele, precisariam ser implementadas em cada serviço individualmente.

Responsabilidades centrais:

ResponsabilidadeO que faz
AutenticaçãoValida tokens antes de chegar aos serviços; serviços recebem identidade já verificada
Rate limitingLimita requisições por cliente, IP ou rota; protege os serviços de abuso
RoteamentoDireciona /orders/* para o serviço de pedidos, /users/* para o serviço de usuários
SSL terminationGerencia certificados HTTPS centralmente
Logging e observabilidadeRegistra todas as requisições em um único ponto; correlação de traces
Transformação de payloadAdapta formatos entre clientes e serviços quando necessário
ClienteAPI Gateway → autenticação → rate check → roteamento → Serviço A | Serviço B

O API Gateway não executa lógica de negócio. É infraestrutura de entrada: pré-processamento e roteamento.

Ferramentas comuns: AWS API Gateway, Kong, Nginx, Traefik, Caddy.

Estratégias para Escalar

Além de instâncias e balanceadores, há camadas de escala que não exigem mais servidores:

CDN para assets estáticos: imagens, JS, CSS e fontes servidos a partir de nós geograficamente próximos ao usuário. Zero carga no servidor de aplicação para esses recursos.

Cache na borda: respostas de API cacheadas no Redis ou Memcached. Requisições repetidas não chegam ao banco.

RequisiçãoCache hit → resposta em < 1ms
RequisiçãoCache miss → banco → armazena → resposta

Read replicas: para sistemas com muito mais leitura do que escrita, réplicas de leitura distribuem 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, enfileirar e processar em background. O servidor de aplicação responde rápido; o worker (trabalhador) absorve o pico no seu próprio ritmo.

Anti-Overengineering

A maioria dos projetos nunca vai precisar de escala horizontal, load balancer dedicado ou múltiplas read replicas. A decisão errada é investir nessa infraestrutura antes de ter o problema.

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 fronteiras de domínio ou times impuserem isolamento real

Cada etapa só faz sentido depois que a anterior foi esgotada. Pular etapas aumenta complexidade sem benefício proporcional.

Sinais de que é hora de escalar:

SinalAção correspondente
CPU ou memória consistentemente acima de 70%Escala vertical primeiro
Tempo de resposta crescendo com o volumeRevisar queries e adicionar cache
Máquina maior não resolve maisAvaliar escala horizontal
Um módulo tem tráfego radicalmente diferente dos demaisConsiderar extração cirúrgica

O que não fazer 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 complexidade de leitura/escrita que justifique

Referência rápida

TécnicaQuando usarCusto de adoção
Escala verticalPrimeiro passo sempreNenhum (sem mudança de código)
Cache (Redis)Leitura frequente, escrita infrequenteBaixo (lib + Redis)
CDNAssets estáticos com usuários distribuídosBaixo (configuração de DNS)
Load BalancerTráfego que uma instância não absorveMédio (app deve ser stateless)
Read ReplicaLeitura virou gargalo no bancoMédio (configuração de banco)
API GatewayMúltiplos serviços ou autenticação centralizadaMédio (configuração e routing)
MicrosserviçosIsolamento real por domínio ou timeAlto (complexidade operacional)

Desenvolvido por @thiagocajadev · Fork baseado no repositório pmndrs/docs · Poimandres.