Quando um serviço não aguenta mais a carga, existem duas direções possíveis: colocar uma máquina maior no lugar da atual, ou colocar mais máquinas trabalhando em paralelo. A primeira é escalabilidade vertical, a segunda é horizontal. A maioria das equipes trata isso como uma bifurcação, como se fosse preciso escolher um caminho e abandonar o outro. Na prática, todo sistema que escala bem usa os dois ao mesmo tempo, só que em camadas diferentes do problema.
O que é escalar verticalmente
Escalar verticalmente é aumentar a capacidade de uma única instância: mais CPU, mais memória, disco mais rápido. É a opção mais simples de implementar, muitas vezes é literalmente trocar o tipo de instância num provedor de nuvem e reiniciar o serviço. Não exige mudança de arquitetura, não exige que a aplicação saiba lidar com múltiplas réplicas, não exige balanceador de carga.
A limitação é física e financeira. Existe um teto de quanto uma única máquina consegue crescer, e esse crescimento não é linear em custo: dobrar CPU e memória de uma instância raramente custa duas vezes mais, em muitos provedores custa proporcionalmente mais caro à medida que a instância fica maior.
O que é escalar horizontalmente
Escalar horizontalmente é adicionar mais instâncias rodando a mesma aplicação, e distribuir a carga entre elas. Em teoria, o crescimento é praticamente ilimitado: se uma instância aguenta X requisições, dez instâncias aguentam, em tese, 10X. Na prática, esse resultado só se sustenta se a aplicação foi desenhada para funcionar assim.
Aplicações que guardam estado em memória local, que dependem de sessão fixada num servidor específico, que fazem locks em arquivo local, ou que assumem que existe apenas uma instância rodando por vez, simplesmente quebram quando você tenta escalar horizontalmente. Não é uma questão de configurar mais réplicas no Kubernetes, é uma questão de reescrever partes da aplicação para ela se tornar stateless.
Por que "ou um, ou outro" é a pergunta errada
Tratar vertical e horizontal como concorrentes ignora que eles resolvem problemas diferentes. Horizontal resolve disponibilidade e elasticidade: o que acontece quando uma instância cai, e como absorver um pico de tráfego sem pagar por aquela capacidade o mês inteiro. Vertical resolve o quanto cada unidade de trabalho custa: se cada réplica está dimensionada certo, ou se está desperdiçando CPU e memória que ninguém mediu, o mesmo ponto que já tratamos no post anterior sobre CPU e memória.
Uma arquitetura só horizontal, com réplicas superdimensionadas, paga o preço da ineficiência multiplicado pelo número de réplicas. Dez instâncias com o dobro do recurso necessário custam dez vezes mais desperdício do que uma só. Uma arquitetura só vertical, por outro lado, tem um teto de crescimento e um único ponto de falha, não importa quão bem dimensionada esteja aquela máquina. Nenhuma das duas, sozinha, é suficiente para operar em escala com custo sob controle.
Como as duas dimensões convivem na prática
O padrão que funciona é calibrar as duas coisas em paralelo, não em sequência. Primeiro, definir o tamanho certo de cada réplica individual, com base em uso real de CPU e memória em pico, não em achismo. Depois, definir quantas réplicas desse tamanho certo são necessárias, e deixar o autoscaling horizontal responder à variação de demanda ao longo do dia. A réplica bem dimensionada é o que faz o autoscaling horizontal custar o que deveria custar, em vez de multiplicar desperdício por instância.
Isso muda a pergunta de "vertical ou horizontal" para duas perguntas separadas, respondidas continuamente: cada réplica está no tamanho certo, e o número de réplicas está acompanhando a demanda real.
O erro mais comum: mexer em uma dimensão e esquecer a outra
O erro mais caro que vemos não é escolher a direção errada, é ajustar uma dimensão e nunca revisar a outra. Times que configuram autoscaling horizontal e nunca mais questionam se o tamanho de cada réplica está certo, carregando anos de superdimensionamento por instância multiplicado por dezenas de réplicas. E times que otimizam o tamanho da instância uma única vez, no início do projeto, e nunca revisitam se a aplicação já deveria ter ganhado uma camada de réplicas para não depender de uma única máquina.
Como decidir na prática
Em vez de perguntar "vertical ou horizontal", vale medir duas coisas em paralelo e continuamente: qual é o uso real de CPU e memória de cada réplica em pico, comparado ao que está provisionado, e se a aplicação já suporta rodar em múltiplas instâncias sem quebrar. A primeira resposta ajusta o tamanho de cada unidade. A segunda decide se, e quanto, faz sentido crescer horizontalmente em cima daquele tamanho já calibrado.
Como a Henceforth ajuda
Fazemos esse diagnóstico nas duas dimensões ao mesmo tempo: medimos o tamanho certo de cada réplica com base em uso real de CPU e memória, e avaliamos a arquitetura de escalabilidade horizontal por cima disso. Já vimos empresas pagando por clusters grandes cheios de réplicas superdimensionadas, e empresas travadas numa única máquina gigante sem nenhuma camada de redundância. Nos dois casos, o problema nunca foi escolher o lado errado, foi calibrar só um lado e esquecer o outro.
Se você não sabe, com segurança, se cada réplica da sua infraestrutura está no tamanho certo e se o número delas acompanha a demanda real, fale com a nossa equipe e vamos descobrir juntos.