Cache não é otimização. É sobrevivência.

Cache não é otimização. É sobrevivência.

Japa Tela Preta #8

O começo é sempre simples

No início, quase todo sistema nasce simples. Uma API recebe a requisição, consulta o banco de dados e retorna o resultado. Sem camadas intermediárias, sem complexidade desnecessária, sem grandes preocupações com performance. E isso faz sentido. Enquanto o volume é pequeno, esse modelo funciona muito bem. As consultas são rápidas, o banco responde com folga e tudo parece sob controle. Nesse estágio, pensar em cache, filas ou qualquer outro mecanismo mais sofisticado soa como exagero. Parece algo que pode ser deixado para depois, sem impacto real no funcionamento do sistema.

Quando o crescimento começa a cobrar o preço

Mas todo sistema que cresce passa por um momento inevitável. O momento em que o “simples” deixa de ser suficiente. Esse ponto raramente chega de forma abrupta. Ele começa com pequenos sinais que, isoladamente, parecem inofensivos. Uma consulta que antes era instantânea passa a levar um pouco mais de tempo. Um endpoint específico começa a oscilar na resposta. O consumo de CPU ou I/O do banco aumenta sem uma explicação clara. No início, esses sintomas são tratados como problemas pontuais. Ajusta-se um índice, melhora-se uma query, e o sistema volta a responder bem. Só que, conforme o crescimento continua, fica evidente que o problema não está apenas na forma como os dados são consultados, mas na frequência com que isso acontece. A mesma informação passa a ser solicitada repetidamente, por usuários diferentes, em intervalos muito curtos.

O erro de tratar cache como luxo

É nesse momento que surge uma pergunta que muda completamente a forma de pensar o sistema: por que estamos recalculando ou buscando a mesma coisa o tempo todo? A resposta, na maioria das vezes, é simples. Porque o sistema foi construído assumindo que cada requisição precisa ir até a fonte de verdade. Esse modelo funciona bem em pequena escala, mas começa a se tornar caro — em termos de tempo e de recursos — conforme o uso cresce. E é aqui que muita gente comete um erro clássico: tratar cache como um luxo, como uma camada de otimização que pode ser adicionada depois. Essa mentalidade é perigosa, porque quando você deixa para pensar em cache apenas quando o sistema já está sofrendo, você já está reagindo, e não projetando.

Cache como mecanismo de sobrevivência

A verdade é mais direta do que parece confortável admitir. Cache não é sobre deixar o sistema mais rápido. É sobre impedir que ele pare de funcionar. Em sistemas que escalam, o gargalo não está apenas na complexidade da lógica, mas no número de vezes que ela precisa ser executada. Sem cache, cada requisição representa um custo completo. Com cache, múltiplas requisições passam a compartilhar o mesmo resultado, transformando esse custo em algo amortizado. O impacto disso é profundo. Ao introduzir cache, você reduz a carga sobre o banco de dados, melhora o tempo de resposta e cria uma camada de proteção contra picos de acesso. Sem essa proteção, qualquer aumento repentino de tráfego pode levar o banco ao limite, afetando todo o sistema. Com cache, boa parte das requisições sequer chega à fonte de dados.

Os desafios que vêm junto com o cache

Mas cache não vem sem custo. Armazenar dados em memória é relativamente simples. O desafio está em garantir que esses dados continuam corretos ao longo do tempo. Surge então um dos problemas mais conhecidos da engenharia de software: a invalidação de cache. Saber exatamente quando um dado deixou de ser válido exige entendimento profundo do domínio e dos fluxos do sistema. Invalidar cedo demais reduz a eficiência. Invalidar tarde demais pode levar a inconsistências. Não existe uma resposta universal, apenas decisões baseadas em contexto.

Além disso, ao introduzir cache, você aceita um trade-off importante. Nem sempre o dado servido será o mais atualizado possível. E isso, ao contrário do que muitos imaginam, não é necessariamente um problema. Em muitos cenários, alguns segundos — ou até minutos — de defasagem são perfeitamente aceitáveis em troca de ganhos significativos de performance e estabilidade. Esse é o terreno da consistência eventual, onde o objetivo deixa de ser refletir o estado exato do sistema em tempo real e passa a ser garantir que, ao longo do tempo, o sistema converge para o estado correto.

Eficiência como estratégia de crescimento

Outro ponto importante é o impacto no negócio. Um sistema mais rápido melhora a experiência do usuário. Um sistema mais estável reduz falhas e aumenta a confiança. Um sistema mais eficiente reduz custos operacionais e permite escalar sem que cada novo usuário represente um aumento proporcional de carga na infraestrutura. Em outras palavras, cache não é apenas uma decisão técnica. É uma decisão estratégica.

O ponto de virada

Em algum momento, todo sistema precisa abandonar a ideia de que tudo deve ser resolvido diretamente na fonte. Esse é o ponto de virada. A partir daí, o foco deixa de ser apenas a correção isolada de cada operação e passa a ser a sustentabilidade do sistema como um todo. É quando você começa a projetar não apenas para funcionar, mas para continuar funcionando sob pressão.

Conclusão

No início, cache parece desnecessário. Depois, parece uma melhoria. E, eventualmente, você percebe que ele é essencial. Porque em sistemas reais, o desafio não é apenas responder corretamente, mas continuar respondendo corretamente enquanto o sistema cresce, enquanto a carga aumenta e enquanto o mundo real começa a impor suas próprias regras.

Cache não é sobre performance.

É sobre sobrevivência.

Foto de Willian Sanada
Willian Sanada