Uma aplicação costuma começar pequena: uma instância da API, um banco de dados e poucos usuários. Com o crescimento do tráfego, essa mesma estrutura pode passar a responder lentamente, acumular requisições ou ficar sem CPU e memória.
Nesse momento, existem duas direções principais para aumentar a capacidade:
Escala vertical: servidor pequeno → servidor maior
Escala horizontal: 1 servidor → vários servidores
As duas estratégias são úteis. A escolha não é uma disputa entre uma solução “antiga” e outra “moderna”, mas uma decisão sobre capacidade, custo, disponibilidade e complexidade.
O que é escalabilidade?
Escalabilidade é a capacidade de um sistema atender ao crescimento da demanda sem perder, de forma inaceitável, desempenho ou confiabilidade.
Essa demanda pode crescer de maneiras diferentes:
- Mais requisições por segundo;
- Mais usuários simultâneos;
- Mais dados armazenados;
- Operações mais pesadas;
- Picos maiores ou mais frequentes;
- Mais tarefas processadas em segundo plano.
Um sistema escalável não precisa ter capacidade infinita. Ele precisa conseguir aumentar sua capacidade de maneira previsível, dentro dos limites técnicos e financeiros do produto.
Também é importante separar escalabilidade de desempenho. Otimizar uma consulta pode fazer o sistema atual trabalhar melhor. Escalar aumenta os recursos disponíveis para suportar mais carga. Na prática, normalmente devemos remover desperdícios óbvios antes de comprar ou adicionar infraestrutura.
O que é escalabilidade vertical?
Escalabilidade vertical, também chamada de scale up, consiste em aumentar os recursos de uma única máquina.
Por exemplo:
Antes Depois
2 vCPUs 16 vCPUs
8 GB de memória → 64 GB de memória
100 GB de disco SSD 1 TB de disco SSD
Também podemos fazer o movimento inverso, chamado de scale down, quando reduzimos os recursos porque a capacidade está ociosa.
Na escala vertical, a arquitetura da aplicação pode permanecer praticamente igual. A API continua em uma instância e o banco continua em um nó, mas ambos passam a executar em máquinas mais potentes.
Quando a escala vertical funciona bem?
Ela costuma ser uma boa primeira opção quando:
- O sistema ainda cabe confortavelmente em uma máquina;
- Queremos uma mudança rápida e operacionalmente simples;
- A aplicação não está preparada para funcionar em várias instâncias;
- O componente é difícil de distribuir, como certas cargas de banco de dados;
- O custo da máquina maior ainda é aceitável;
- Uma interrupção curta durante a mudança de capacidade é tolerável.
Um banco relacional, por exemplo, frequentemente começa escalando verticalmente. Mais memória permite manter mais páginas e índices em cache; mais CPU ajuda consultas e operações concorrentes; discos mais rápidos reduzem o tempo de entrada e saída.
Limites da escala vertical
O primeiro limite é físico: sempre existe uma máquina máxima disponível no provedor ou no datacenter.
O segundo é econômico. Máquinas maiores geralmente ficam progressivamente mais caras, e dobrar recursos nem sempre dobra a capacidade real. A aplicação pode continuar limitada pelo banco, pela rede, pelo disco, por locks ou por uma dependência externa.
O terceiro é a falha. Uma máquina maior ainda é uma única máquina. Se ela ficar indisponível e não houver redundância, todo o serviço pode parar.
Usuário → Servidor grande → Banco
✕
falha interrompe o serviço
Escala vertical, portanto, aumenta capacidade, mas não cria alta disponibilidade por si só.
O que é escalabilidade horizontal?
Escalabilidade horizontal, também chamada de scale out, consiste em adicionar mais máquinas ou instâncias para dividir o trabalho.
┌→ API 1
Usuário → Load Balancer ─┼→ API 2
└→ API 3
Quando a demanda diminui, podemos remover instâncias. Esse movimento é chamado de scale in.
O balanceador de carga recebe as requisições e escolhe uma instância saudável para atendê-las. Se o trabalho estiver bem distribuído, novas instâncias aumentam a capacidade total do serviço.
O requisito mais importante: dividir o trabalho
Adicionar máquinas só ajuda quando o trabalho pode ser particionado ou distribuído.
Servidores de aplicação stateless, que não guardam estado de sessão ou arquivos locais necessários à próxima requisição, são mais fáceis de escalar horizontalmente:
Requisição 1 → API 1
Requisição 2 → API 3
Requisição 3 → API 2
Qualquer instância pode atender qualquer requisição porque o estado necessário está em um local compartilhado, como um banco, cache ou object storage.
Se a API 1 guardar a sessão apenas em sua memória, uma requisição seguinte enviada à API 2 pode não reconhecer o usuário. Algumas formas de resolver isso são:
- Armazenar a sessão em um repositório compartilhado;
- Usar tokens verificáveis por todas as instâncias, quando apropriado;
- Externalizar arquivos para object storage;
- Evitar depender do disco local entre requisições.
Sessões persistentes no balanceador, conhecidas como sticky sessions, podem manter um usuário na mesma instância, mas não eliminam o problema. Elas dificultam a distribuição uniforme e exigem uma estratégia para quando aquela instância falhar.
Escala horizontal não é capacidade grátis
Várias instâncias introduzem novos desafios:
- Balanceamento de carga e health checks;
- Descoberta e remoção de instâncias com falha;
- Concorrência sobre dados compartilhados;
- Logs e métricas espalhados;
- Deploys e configuração consistentes;
- Comunicação pela rede, que pode atrasar ou falhar;
- Custo mínimo de manter redundância.
Além disso, o gargalo pode apenas mudar de lugar:
┌→ API 1 ─┐
Load Balancer ───┼→ API 2 ─┼→ Banco sobrecarregado
└→ API 3 ─┘
Triplicar as instâncias da API não triplica a capacidade do sistema se todas disputam as mesmas conexões e os mesmos recursos de um banco já saturado.
Escalar aplicações e bancos não é a mesma coisa
Uma camada de aplicação stateless costuma aceitar escala horizontal com relativa facilidade. Dados persistentes tornam o problema mais difícil porque precisam manter regras de consistência e sobreviver a falhas.
Para aumentar a capacidade de leitura de um banco, podemos usar réplicas:
┌→ Réplica de leitura 1
Aplicação → Nó primário ─┼→ Réplica de leitura 2
└→ Réplica de leitura 3
Mas réplicas podem apresentar atraso e normalmente não distribuem todas as escritas. Para dividir um conjunto muito grande de dados, pode ser necessário particionamento ou sharding, o que adiciona decisões sobre chave de partição, consultas entre partições, rebalanceamento e transações.
Por isso, dizer apenas “vamos escalar horizontalmente” é incompleto. Precisamos indicar qual componente, qual tipo de carga e como o trabalho ou os dados serão divididos.
Comparação entre escala vertical e horizontal
| Aspecto | Escala vertical | Escala horizontal |
|---|---|---|
| Como cresce | Mais recursos em uma máquina | Mais máquinas ou instâncias |
| Implementação inicial | Geralmente mais simples | Exige distribuição de carga |
| Limite de capacidade | Limitada ao maior hardware disponível | Pode crescer por mais nós, mas não indefinidamente |
| Falhas | Pode manter um único ponto de falha | Pode oferecer redundância entre instâncias |
| Complexidade operacional | Menor no início | Maior por rede, coordenação e observabilidade |
| Elasticidade | Mudanças podem exigir resize ou reinício | Instâncias podem entrar e sair conforme a demanda |
| Adequação comum | Bancos, sistemas menores e cargas difíceis de dividir | APIs stateless, workers e tráfego variável |
Essa comparação descreve tendências, não garantias. Uma arquitetura horizontal mal projetada pode ter pouca disponibilidade, enquanto uma solução vertical com failover bem configurado pode ser bastante resiliente.
Quando utilizar cada estratégia?
Comece pelos requisitos e pelas medições.
Considere escala vertical quando uma máquina maior resolve o gargalo com folga, a simplicidade é valiosa e os limites conhecidos ainda estão distantes. Essa costuma ser uma decisão excelente para produtos em estágio inicial.
Considere escala horizontal quando:
- Uma única máquina se aproxima do limite técnico ou financeiro;
- O tráfego varia e exige elasticidade;
- Precisamos continuar atendendo se uma instância falhar;
- O trabalho pode ser dividido entre instâncias;
- Deploys graduais e substituição de nós são importantes;
- A equipe consegue operar a complexidade adicional.
Muitos sistemas usam uma estratégia híbrida. As instâncias possuem tamanho suficiente para operar com eficiência e a quantidade de instâncias varia conforme a carga.
Máquinas adequadas + múltiplas instâncias + capacidade de crescer e reduzir
Não é necessário escolher uma estratégia para toda a arquitetura. A API pode escalar horizontalmente, o banco pode escalar verticalmente e os workers podem aumentar ou diminuir com o tamanho da fila.
Exemplo prático: uma API de comércio eletrônico
Imagine uma API executada em uma máquina com 4 vCPUs e 8 GB de memória. Em dias comuns, ela utiliza 30% de CPU. Durante uma campanha, a CPU chega a 95%, a fila de requisições cresce e a latência aumenta.
Passo 1: confirmar o gargalo
Antes de escalar, a equipe verifica:
- CPU, memória, disco e rede;
- Latência e taxa de erro por endpoint;
- Consultas lentas e pool de conexões;
- Dependências externas;
- Volume médio e volume de pico.
A medição mostra que o processamento da API consome CPU, enquanto o banco mantém capacidade disponível.
Opção A: escala vertical
A equipe troca a máquina por outra com 8 vCPUs e 16 GB de memória.
1 API com 4 vCPUs → 1 API com 8 vCPUs
É uma mudança simples e pode resolver o pico atual. Porém, a API continua sendo um único ponto de falha e o próximo aumento exigirá outra troca de capacidade.
Opção B: escala horizontal
A equipe prepara a API para não depender de sessão e arquivos locais, adiciona um load balancer e executa três instâncias.
┌→ API 1
Clientes → Load Balancer ─┼→ API 2 → Banco
└→ API 3
Agora uma instância pode sair de serviço sem interromper todas as requisições, e novas instâncias podem ser adicionadas antes da campanha. Em troca, a equipe precisa monitorar o conjunto, configurar health checks e controlar o total de conexões abertas no banco.
Decisão
Se a campanha é pequena, rara e a indisponibilidade de uma instância é aceitável, aumentar a máquina pode ser suficiente. Se os picos são frequentes, a disponibilidade é importante e a demanda continuará crescendo, preparar a escala horizontal tende a trazer mais valor.
Autoscaling e métricas
Autoscaling ajusta automaticamente a quantidade ou o tamanho dos recursos de acordo com sinais observados. Ele pode ser horizontal ou vertical, embora o horizontal seja comum em aplicações stateless.
CPU é uma métrica útil, mas não serve para todos os casos. O sinal deve representar o trabalho que precisa ser absorvido:
- Requisições por segundo para APIs;
- Latência ou número de requisições concorrentes;
- Tamanho e idade da fila para workers;
- Memória para processos que mantêm grandes conjuntos em memória;
- Conexões e tempo de consulta para bancos.
Uma política também precisa considerar o tempo de inicialização das instâncias, limites mínimo e máximo, período de estabilização e capacidade das dependências.
Escalar apenas depois que a latência já está alta pode ser tarde demais. Em eventos previsíveis, aumentar a capacidade antecipadamente pode ser mais seguro do que depender somente de uma reação automática.
Vantagens
Escala vertical
- É simples de entender e adotar;
- Exige poucas mudanças na aplicação;
- Evita coordenação entre várias instâncias;
- Pode resolver rapidamente gargalos de curto e médio prazo.
Escala horizontal
- Permite adicionar capacidade por novas instâncias;
- Facilita redundância e tolerância à falha de um nó;
- Pode acompanhar cargas variáveis com elasticidade;
- Favorece manutenção e deploy gradual sem retirar todo o serviço do ar.
Limitações e trade-offs
| Decisão | Benefício | Custo ou risco |
|---|---|---|
| Aumentar uma máquina | Mudança rápida e simples | Teto de hardware e possível ponto único de falha |
| Adicionar instâncias | Mais capacidade e redundância | Rede, coordenação e operação distribuída |
| Externalizar estado | Qualquer instância atende a requisição | Dependência e carga no armazenamento compartilhado |
| Usar autoscaling | Capacidade acompanha a demanda | Reação atrasada, oscilações e limites das dependências |
Nenhuma estratégia elimina a necessidade de planejar capacidade. Sistemas horizontais também encontram limites: banco de dados, throughput de rede, cotas do provedor, regiões, locks e operações que não podem ser paralelizadas.
Erros comuns
Escalar sem medir o gargalo
Adicionar servidores à API não resolve uma consulta lenta, uma dependência externa saturada ou um lock global. Primeiro identifique qual recurso limita o throughput e confirme a hipótese com métricas.
Confundir escala horizontal com alta disponibilidade
Ter três instâncias na mesma infraestrutura não garante resiliência. Uma falha compartilhada de banco, zona, configuração ou credencial pode derrubar todas elas. Disponibilidade exige analisar modos de falha, não apenas contar servidores.
Manter estado apenas na instância
Sessões, uploads e tarefas guardados localmente tornam as instâncias dependentes entre si e dificultam substituição, balanceamento e recuperação.
Ignorar o banco ao escalar a aplicação
Mais APIs podem abrir mais conexões e gerar mais consultas. Sem limites de concorrência, cache adequado ou evolução da camada de dados, a escala horizontal pode sobrecarregar o banco mais rapidamente.
Escalar para compensar código ineficiente
Infraestrutura adicional pode esconder temporariamente consultas sem índice, loops caros ou chamadas repetidas. Otimização e escala são ferramentas complementares, não substitutas.
Projetar para uma escala imaginária
Distribuir um sistema cedo demais aumenta o custo de desenvolvimento e operação. Devemos considerar o crescimento esperado, mas resolver primeiro o problema real com margem razoável.
Perguntas de entrevista
- Qual é a diferença entre escalabilidade vertical e horizontal?
- Quando você escolheria scale up antes de scale out?
- Por que uma aplicação stateless é mais fácil de escalar horizontalmente?
- Adicionar mais instâncias da API sempre aumenta o throughput do sistema? Por quê?
- Como sessões e arquivos locais afetam a escala horizontal?
- Quais métricas você usaria para configurar autoscaling de uma API e de um worker?
- Como a estratégia muda quando o gargalo está no banco de dados?
- Escala horizontal garante alta disponibilidade? Quais falhas ainda podem afetar todas as instâncias?
Próximos conteúdos
Depois de entender as duas direções de crescimento, aprofunde os sinais usados para decidir quando escalar: latência, throughput, taxa de erros e saturação.
Em seguida, estude os componentes que tornam a escala horizontal possível, como load balancers, cache, replicação e particionamento. O estudo de caso de um encurtador de URLs ajuda a observar como essas decisões se combinam em uma arquitetura completa.
Guarde este modelo mental:
Medir a demanda
↓
Encontrar o gargalo
↓
Otimizar o desperdício evidente
↓
Escolher scale up, scale out ou ambos
↓
Medir novamente
Escalabilidade não é adicionar máquinas por reflexo. É aumentar a capacidade do componente certo, no momento certo, conhecendo o próximo limite que essa decisão pode criar.