Cache de Aplicação: Como Implementar sem Servir Dado Velho
O que é cache de aplicação
Cache de aplicação é a prática de guardar o resultado de um processamento caro, como uma consulta ao banco ou uma chamada a uma API externa, para reaproveitar essa resposta na próxima vez que ela for pedida. Em vez de refazer o trabalho, o sistema lê de um lugar mais rápido.
O ganho é direto: uma consulta que levava 200ms passa a responder em menos de 5ms quando servida da memória. O custo também é direto, só que menos óbvio no início. A partir do momento em que você guarda uma cópia de um dado, existem duas versões dele no sistema: a original, que pode mudar, e a copiada, que fica parada até alguém decidir atualizá-la ou descartá-la. Todo problema de cache de aplicação nasce dessa distância entre as duas.
Onde colocar cada camada de cache
Cache de aplicação não é uma coisa só. São três camadas com escopos diferentes, e escolher a errada é a causa mais comum de cache que não ajuda em nada.
Memória local, dentro do próprio processo da aplicação, é a mais rápida e a mais simples de implementar. O problema aparece quando você tem mais de uma instância rodando: cada processo guarda sua própria cópia, então duas requisições para o mesmo dado podem receber respostas diferentes dependendo de qual instância atendeu.
Redis, ou outro armazenamento externo compartilhado, resolve esse problema. Todas as instâncias leem e escrevem no mesmo lugar, o cache sobrevive a um deploy ou reinício da aplicação, e você ganha controle fino sobre expiração por chave. O custo é uma chamada de rede a mais, ainda muito mais barata do que refazer a consulta original.
HTTP e CDN atacam o problema de outro ângulo: em vez de acelerar a resposta do seu servidor, eles evitam que a requisição chegue até ele. Um cabeçalho Cache-Control bem configurado, ou uma regra de cache na CDN, faz o navegador ou o edge responderem sozinhos, sem gastar um ciclo do seu back-end.
Como implementar cache de aplicação na prática
A ordem importa. Ligar o cache antes de entender o que está guardando é o caminho mais curto para um bug difícil de reproduzir.
- Meça o custo real da operação antes de cachear qualquer coisa. Se a consulta já responde em 3ms, adicionar cache só aumenta a complexidade sem ganho perceptível.
- Defina a chave incluindo todo parâmetro que muda o resultado. Um cache de
/produtos?categoria=1que ignora o parâmetropaginana chave devolve a página 1 para todo mundo. - Escolha o TTL, o tempo de vida da entrada no cache, olhando para a frequência real de mudança do dado. Um catálogo de produtos que muda uma vez por dia aguenta um TTL de horas. Um saldo de conta corrente não aguenta nem um minuto.
- Escolha onde guardar: memória local para dado que não precisa ser consistente entre instâncias, Redis para o que precisa, HTTP e CDN para resposta pública que não depende de quem está logado.
- Registre taxa de acerto e taxa de erro do cache. Sem esse número, ninguém sabe se o cache está sendo usado ou só ocupando memória à toa.
Como evitar servir dado velho
Servir dado velho é o risco central de qualquer cache de aplicação, e existem duas formas de reduzi-lo: TTL curto e invalidação por evento. Elas não são excludentes, e a maioria dos sistemas usa as duas juntas.
TTL curto é a estratégia mais simples: a entrada expira sozinha depois de um tempo fixo, e a próxima leitura busca o dado atualizado. Funciona bem quando um atraso pequeno entre a mudança real e a mudança refletida no cache é aceitável, como em um contador de curtidas.
Invalidação por evento é mais precisa: quando o dado muda, o próprio código que fez a mudança apaga ou atualiza a entrada correspondente no cache. Um UPDATE no preço de um produto dispara a remoção da chave produto:123 no mesmo momento, em vez de esperar o TTL vencer. Exige mais disciplina no código, porque toda rota de escrita precisa lembrar de invalidar a chave certa, mas fecha a janela de inconsistência quase por completo.
O erro mais comum é escolher um TTL longo para reduzir carga no banco e não implementar invalidação por evento nenhuma. O sistema fica rápido e, ao mesmo tempo, capaz de mostrar um preço errado por horas sem gerar nenhum erro no log. Do ponto de vista do monitoramento, é um bug silencioso: para saber se isso está acontecendo em produção, vale a pena olhar como estruturar observabilidade de aplicação com métricas específicas de cache, não só de erro.
Quando cache de aplicação não é a solução
Cache de aplicação resolve leitura repetida de um dado que muda pouco. Ele não resolve escrita lenta, e não resolve uma consulta mal escrita que faz SELECT * numa tabela sem índice na coluna certa. Colocar cache em cima de uma consulta ruim esconde o sintoma sem corrigir a causa, e o problema volta assim que o cache expira ou a chave muda.
Também vale desconfiar de cache em dado que muda a cada requisição, como um resultado de busca com filtro livre de texto. Nesse caso a taxa de acerto fica tão baixa que o cache só adiciona complexidade e mais um lugar para o bug de dado velho aparecer.
Bem aplicado, na camada certa e com plano de invalidação definido antes da primeira linha de código, cache de aplicação continua sendo uma das formas mais baratas de tirar carga do banco e reduzir tempo de resposta sem tocar na arquitetura do sistema.
Se sua aplicação precisa de uma estratégia de cache desenhada para o seu volume real de acesso, fale com a gente.