← Blog

Escalabilidade vertical e horizontal: quando mais RAM é o movimento errado

O endpoint ficou lento. O reflexo é quase automático: aumentar RAM, subir a CPU, pedir uma instância maior. Às vezes isso funciona. Muitas vezes só adia o diagnóstico e encarece o mesmo desenho.

Escalabilidade não é potência bruta. É a capacidade do sistema de acompanhar a demanda sem transformar cada pico em incidente. Se você mede só “a máquina está cheia”, trata sintoma. Se mede tempo de resposta e o que acontece dentro de cada requisição, começa a ver o problema.

O que a métrica está pedindo

Em aplicação web, a métrica que o usuário sente é o tempo de resposta. Query lenta, relatório pesado e envio de e-mail na mesma request aparecem todos como “o site travou”. Do lado do servidor, CPU alta e memória saturada são consequências, não o mapa.

Antes de comprar recurso, pergunte: o que esta requisição precisa terminar antes de responder? Se a resposta inclui trabalho que o usuário não precisa esperar — e-mail, thumbnail, exportação, chamada a um parceiro lento —, o gargalo não é falta de RAM. É o desenho síncrono.

Um sistema mais rápido também é mais barato de escalar. Cada requisição que libera o processo cedo devolve capacidade para a próxima. Escalar um endpoint que segura o worker por oito segundos custa mais do que escalar um que responde em oitenta milissegundos e deixa o resto para depois.

Vertical: um servidor mais gordo

Escalabilidade vertical é acrescentar recurso na mesma caixa: mais núcleos, mais memória, disco mais rápido. O modelo mental é simples. O código quase não muda. O banco que “não aguenta” ganha buffer. O PHP-FPM ganha filhos. O problema parece resolvido na fatura.

O limite aparece cedo. Existe um teto de hardware. Existe um teto de preço. Existe um teto de risco: uma máquina só continua sendo um ponto único de falha, agora mais caro. E existe um teto conceitual: se cada request faz I/O externo e espera, mais CPU não encurta a espera da rede.

Vertical ainda é o primeiro passo certo em muitos casos. Um servidor subdimensionado, um pool de processos minúsculo, um MySQL sem memória para índices quentes — aí sim, RAM resolve. O erro não é usar vertical. É usá-la como substituto de arquitetura.

Horizontal: mais peças, não uma peça maior

Escalabilidade horizontal é acrescentar instâncias: mais processos, mais workers, mais servidores atrás de um balanceador. Cada peça faz uma fatia do trabalho. A demanda sobe, você replica. A demanda desce, você reduz.

Horizontal exige outra disciplina. Estado local vira problema. Sessão em arquivo no disco da máquina A não existe na máquina B. Cache em memória de um processo não serve ao outro. Upload gravado em /tmp some no próximo hop. Sem esse cuidado, “vários servidores” só multiplica inconsistência.

A recompensa é o eixo certo de crescimento. Workers de fila podem crescer sem crescer a API. Leitura pode crescer sem crescer escrita. Relatório pode crescer sem prender o checkout.

flowchart TD
  A[Request lenta] --> B{O usuário precisa esperar?}
  B -->|Sim, é o núcleo| C[Medir e otimizar]
  C --> D{Gargalo é CPU/RAM?}
  D -->|Sim| E[Escala vertical]
  D -->|Não| F[Separar o trabalho]
  B -->|Não| F
  F --> G[Publicar na fila]
  G --> H[API responde cedo]
  H --> I[Workers horizontais]
  classDef ouro fill:#FBF5E4,stroke:#C9A227,color:#0B1F18,stroke-width:1.4px
  classDef verde fill:#F3FAF7,stroke:#1E7A57,color:#0B1F18,stroke-width:1.4px
  classDef fim fill:#14513B,stroke:#0F3328,color:#FBFAF6,stroke-width:1.4px
  class A ouro
  class B,C,D,F,G verde
  class E,H,I fim

Quando adicionar RAM é o movimento errado

RAM é o movimento errado quando o tempo está em espera, não em computação. Enviar e-mail SMTP, gerar PDF, chamar gateway, percorrer milhares de linhas para um relatório “na hora” — nada disso some porque a máquina ganhou 16 GB.

Também é o movimento errado quando você ainda não sabe o teto atual. Sem perfil, sem log de duração por rota, sem olhar fila de processos, “mais RAM” é um palpite caro. Já vi pool de PHP com poucos filhos e memória ociosa: o servidor não estava pequeno; estava mal configurado. Já vi query sem índice fazendo full scan: o banco pedia índice, não instância maior.

Há um terceiro caso, mais sutil. O sistema cresce em usuários, mas o trabalho por request também cresce — mais jobs no mesmo request, mais integrações síncronas, mais “já que estamos aqui”. Vertical cobre o crescimento por um trimestre. Depois o mesmo desenho volta a doer, só que a conta já é alta e o medo de mudar também.

Fila e assíncrono: o truque que destrava o horizontal

Mensageria não é um adorno de arquitetura. É o mecanismo que transforma “uma request faz tudo” em “uma request registra a intenção”. Publicar numa fila é, em geral, milissegundos. Enviar o e-mail pode ser segundos. A API devolve 202 ou 200 com “vamos avisar”, e o worker trata o restante.

Isso habilita horizontal de verdade. A API escala com o tráfego de cliques. Os workers escalam com o volume de tarefas. Se a fila enche, você sobe consumidores, não a máquina do front. Se o e-mail do provedor atrasar, o checkout não atrasar junto.

O mesmo padrão vale para relatório pesado, redimensionamento de imagem, recálculo de ranking, sincronização com ERP. Tudo que é lento e não precisa estar na resposta imediata pode sair do caminho crítico. Tudo que precisa estar — saldo, autorização, idempotência do pagamento — permanece síncrono, medido e curto.

Situação Primeiro movimento Por quê
Pool de processos saturado, CPU baixa Ajustar pool ou vertical leve Capacidade ociosa mal usada
Query lenta, mesmo com pouca carga Índice, plano, cache pontual Hardware não corrige N+1
E-mail ou PDF na request Fila + worker Espera externa no caminho crítico
Pico de leitura, escrita estável Réplicas / mais instâncias Eixo de crescimento diferente
Uma caixa só, medo de cair Horizontal + estado externo Vertical não remove SPOF

Três perguntas antes de escalar

  1. Qual é o percentil de tempo de resposta que dói — p50, p95, p99?
  2. Onde esse tempo é gasto: CPU, disco, lock, rede, espera de terceiro?
  3. Esse trabalho precisa terminar para o usuário receber a resposta?

Se você não responde as três, vertical é chute. Se responde e o trabalho não precisa estar na request, horizontal via fila costuma ser o caminho. Se o trabalho precisa e é CPU de verdade, aí sim, máquina maior ou algoritmo melhor.

Escalar bem é escolher o eixo. Para cima, quando o recurso da caixa é o limite. Para o lado, quando a unidade de trabalho já pode ser repetida. A pressa de “só sobe a RAM” mistura os dois e deixa a arquitetura presa numa conta que só cresce.

Na Programming One essa conversa aparece no código: o projeto cresce até o servidor único não bastar, e a solução deixa de ser “mais RAM” para virar processo, fila e réplica.

Leia também: Mensageria: por que filas melhoram a resposta e Load balancer, Nginx e vários servidores.

#Escalabilidade#Arquitetura#Performance#Servidores

Thiago Nogueira

Autor de A Caixa Mágica e das séries Programming One e AI One na Editora Pensar Bem.

Capa de Python One

Python One

Do primeiro print à API REST em produção.