Imagine que o seu sistema é uma geladeira.
Cada item ali dentro tem um propósito — frutas frescas, leite, uma marmita que sobrou do jantar. Mas, se você nunca jogar fora o que vence e continuar colocando mais comida, uma hora não há espaço. E pior: quando for comer, o gosto azedo vai te lembrar que capacidade sem controle é um desperdício.

Essa é a melhor metáfora possível para entender caches.
Em engenharia de software, um bom cache não é apenas sobre velocidade — é sobre manter o equilíbrio entre espaço e frescor, entre custo e correção.
Dois mecanismos garantem isso: Eviction e TTL (Time To Live).
Eviction é o ato de “limpar a geladeira” quando ela está cheia.
TTL é a data de validade colada nos potes.
Juntos, eles mantêm o sistema saudável: uma geladeira limpa e comida segura. Separados, criam caos — um caos que pode custar milhões.
O mito do cache “inteligente”
É comum ouvir frases como “vamos colocar um Redis e resolver o gargalo” ou “esse dado muda pouco, vamos cachear”.
Mas, na prática, caches são como remédios fortes: aliviam sintomas de latência e carga, mas se usados sem dosagem e acompanhamento, matam o paciente.
Quando um sistema começa a crescer — digamos, um e-commerce com milhões de acessos diários — o cache passa a ser um dos componentes mais críticos da arquitetura. Ele está em todos os lugares: na borda (CDNs como Cloudflare), nos middlewares (Redis, Memcached), e até dentro do código, em caches locais de in-memory.
Mas há uma armadilha: quanto mais camadas você adiciona, mais fácil é perder o controle de quando os dados foram criados, por quem e até se ainda são válidos.
Em 2019, um grande varejista brasileiro enfrentou um problema curioso: as promoções de Black Friday começaram à meia-noite, mas parte dos usuários ainda via os preços antigos. O motivo? Um cache de catálogo configurado apenas com LRU. Os itens “mais vistos” eram os que menos expiravam.
Ou seja, o sistema estava cheio de leite vencido.
Por que o LRU sozinho falha
1. Dados obsoletos: as teclas de atalho nunca expiram. O preço de ontem vive para sempre.
2. Memória ociosa: se o cache nunca enche, nada é despejado. As chaves mortas permanecem.
3. Correção quebrada: dados errados são piores do que uma falha.
Por que o TTL sozinho falha
1. Manada trovejante: a expiração chega e todos os clientes correm de volta para a fonte.
2. Espaço desperdiçado: TTLs longos mantêm as chaves frias vivas mesmo que ninguém precise delas.
3. Baixa eficiência: dados antigos monopolizam a memória até que os temporizadores se esgotem.
Eviction e TTL resolvem dois problemas muito diferentes:
- Despejo (LRU/LFU): entra em ação quando a memória está cheia. Otimiza o espaço.
- TTL: entra em ação quando os dados ficam antigos. Otimiza a correção.
Pense em um cache como uma geladeira. Eviction = jogar fora itens quando estiver muito cheio. TTL = datas de validade para que você não beba leite estragado. Juntos = comida fresca e espaço livre.
Analogias a parte, vamos entender um pouco mais esses conceitos
Por que o LRU sozinho não é suficiente
LRU — Least Recently Used — é o algoritmo de substituição mais popular entre caches.
Ele remove os itens menos acessados recentemente para liberar espaço, garantindo que apenas os “quentes” permaneçam.
Na teoria, é uma ideia elegante: por que guardar algo que ninguém usa?

Mas o LRU é cego ao tempo.
Ele se preocupa apenas com frequência de acesso, não com validade de informação.
Em um sistema de e-commerce, isso é uma bomba-relógio: um produto pode ser acessado mil vezes por hora, mas se o preço muda no banco e o cache nunca expira, você está servindo dados obsoletos com confiança absoluta.
Pior: quanto mais popular o item, mais difícil é ele sair da memória. É como um iogurte que todo mundo olha, mas ninguém joga fora.
Um exemplo prático disso vem de um cenário real da Uber.
No início da expansão global, parte dos valores dinâmicos de tarifa eram armazenados em cache local por cidade. Em horários de pico, esses valores eram lidos constantemente — e nunca removidos.
Quando o modelo de preço foi alterado em tempo real, levou minutos até as novas tarifas propagarem.
Minutos de diferença em milhões de corridas.
O cache, que deveria proteger o sistema, protegeu a informação errada.
O LRU é essencial, mas sozinho ele otimiza espaço, não correção. E correção é o que separa um sistema rápido de um sistema confiável.
Por que o TTL sozinho também falha
Agora imagine o oposto: um cache que se baseia apenas em TTL (Time To Live).
Cada item tem um tempo de vida definido — digamos, 10 minutos — e após esse prazo, é automaticamente descartado.
Simples, elegante, previsível.
Mas o problema da simplicidade é que ela raramente sobrevive ao mundo real.
O TTL é ótimo para evitar dados podres, mas causa efeitos colaterais brutais.
Quando várias chaves expiram ao mesmo tempo, todos os clientes voltam a buscar o dado original simultaneamente. Esse fenômeno tem nome: Thundering Herd Problem — o rebanho que pisa na origem.
Em um sistema de recomendação, por exemplo, isso é desastroso.
Imagine milhões de usuários acessando a home da sua loja virtual às 9h da manhã, e o cache de recomendações expira naquele exato momento.
De repente, o backend que gera recomendações — um serviço pesado de machine learning — recebe milhares de requisições em segundos.
Cada instância tenta recalcular os mesmos dados.
Resultado: CPU no máximo, instâncias morrendo e clientes sem resposta.

TTL sozinho também cria desperdício.
Dados que raramente são acessados ainda ocupam memória até o tempo expirar, o que prejudica a eficiência.
E mais: escolher um TTL errado é um dilema sem fim. Curto demais, e o cache perde o propósito. Longo demais, e o dado envelhece.
TTL não é sobre tempo, é sobre contexto.
O equilíbrio: Eviction + TTL
A beleza dos sistemas distribuídos está no equilíbrio entre forças opostas.
Eviction e TTL são dois lados de uma mesma moeda: LRU/LFU otimiza espaço, TTL otimiza verdade.
Pense novamente na geladeira:
LRU é o hábito de jogar fora o que está ocupando espaço. TTL é o rótulo que diz quando algo vence.
Nenhum dos dois, isoladamente, garante uma cozinha saudável.
Mas juntos, criam harmonia.
O mesmo vale para caches.
LRU mantém o cache leve e eficiente, priorizando o que o sistema realmente usa. TTL garante que os dados continuem frescos e coerentes com a origem.
Quando combinados, criam um ciclo virtuoso:
- O dado é inserido com validade (TTL).
- O cache mantém apenas os mais úteis (LRU).
- Quando expira ou precisa de espaço, é removido.
- Quando acessado novamente, é renovado — just in time.
Essa sinergia é o que diferencia um cache reativo de um cache adaptativo.
É o que evita que você sirva preços antigos, catálogos desatualizados ou sessões fantasmas.
Estratégias que vão além do básico
Em arquiteturas maduras, Eviction + TTL são apenas o início.
A indústria evoluiu com padrões que equilibram desempenho e frescor:
- Write-through cache: toda escrita vai para o banco e também para o cache, mantendo coerência imediata.
- Write-back cache: escreve primeiro no cache e posterga a persistência — mais rápido, mas arriscado em caso de falha.
- Refresh-ahead: revalida dados prestes a expirar, evitando o thundering herd.
- Soft TTL: permite usar dados “vencidos” por um curto período enquanto o novo é buscado.
- Cache warming: popula antecipadamente o cache em cenários previsíveis, como eventos sazonais.
Um caso clássico é o da Netflix, que combina várias dessas abordagens.
Os dados de recomendação são atualizados de forma assíncrona (soft TTL), enquanto as configurações de usuários têm write-through, e as métricas de visualização usam eviction baseado em LFU (Least Frequently Used).
Cada tipo de dado tem seu próprio “prazo de validade”.
O cache e o preço da ignorância
Muitos engenheiros enxergam o cache como uma otimização local.
Mas o cache é uma decisão de arquitetura, não uma técnica de performance.
Ele carrega custos invisíveis: invalidação, sincronização, rastreabilidade.
Como Martin Fowler escreveu em Building Evolutionary Architectures, “todo ponto de acoplamento cria tensão entre estabilidade e adaptabilidade”.
O cache é o exemplo perfeito dessa tensão.
Nos bastidores, empresas como Stripe, Shopify e Mercado Livre tratam o cache como um ativo de primeira classe.
Monitoram taxas de cache hit, stale hit ratio e eviction rate em tempo real.
Detectam padrões anômalos — como TTLs expirando em massa — e aplicam progressive backoff.
O cache deixa de ser um “atalho” e se torna uma camada de governança de dados.
Um exemplo prático: o carrinho que nunca expira
Em um e-commerce, o carrinho de compras costuma ser armazenado em cache para reduzir o acesso ao banco.
Mas um bug comum acontece quando o TTL é omitido.
Usuários adicionam itens, voltam dias depois e encontram o mesmo carrinho — mas os preços mudaram.
LRU não ajuda, porque o carrinho é frequentemente acessado.
TTL sozinho tampouco resolve, pois o volume de expirações simultâneas gera picos de tráfego.
A solução elegante é combinar os dois.
Carrinhos antigos expiram após 48h (TTL), mas o sistema também aplica LRU para limitar memória ativa.
Além disso, há um soft TTL: se o cache expirou, o sistema ainda pode exibir o carrinho, mas todos os preços são validados novamente.
O usuário mantém a experiência, e o sistema preserva a integridade.
Cache não é sobre velocidade, é sobre responsabilidade
O que diferencia um engenheiro experiente de um iniciante não é o número de tecnologias que domina, mas a compreensão das consequências.
Caches errados causam o tipo mais perigoso de bug: o bug invisível.
Aquele que retorna o dado certo, na hora errada.
Um cache ideal não é aquele que nunca falha — é o que falha de maneira previsível e controlada.
É o que entende que o dado é perecível, como comida na geladeira, e que ignorar essa natureza é assinar um contrato com a entropia.
Eviction e TTL não são recursos — são compromissos.
E projetar um sistema resiliente é, antes de tudo, aceitar que nada é eterno, nem mesmo o dado que você acabou de gravar.
📚 Leituras recomendadas
- Cache Hit Ratio: medindo o que realmente importa
- Confiabilidade e consistência: construindo sistemas que não quebram sob pressão
- Designing Data-Intensive Applications, Martin Kleppmann
- Building Evolutionary Architectures, Neal Ford, Rebecca Parsons e Patrick Kua