O que e Cache?

Uma camada de armazenamento temporário que guarda resultados de operações caras para reutilizar rapidamente.

Cache e uma técnica fundamental de performance onde resultados de operações lentas ou caras são armazenados temporariamente para serem reutilizados em requisições futuras sem precisar executar a operação novamente. A ideia e simples: se buscar dados do banco de dados leva 100ms, mas retornar dados de um cache em memória leva 1ms, e muito mais eficiente armazenar o resultado da primeira busca e reutilizar para as próximas. Cache e usado em todos os níveis de um sistema moderno: no browser (cache HTTP), nos servidores de borda (CDN), na aplicação (Redis, Memcached), e até dentro do banco de dados (query cache). Uma estrategia de caching bem implementada pode reduzir a latência em 90%, diminuir a carga no banco em 80% e permitir que o sistema suporte muito mais usuários com a mesma infraestrutura.

Tipos de cache por nível

Browser, CDN, aplicação e banco de dados: cada nível tem seu papel.

Cache funciona em múltiplos níveis. Cache do browser: o browser armazena recursos estaticos como imagens, CSS e JavaScript. Headers como Cache-Control e ETag controlam por quanto tempo e se pode ser reutilizado. Cache CDN: servidores de borda distribuídos geograficamente armazenam conteúdo estatico e dinâmico perto dos usuários, reduzindo latência global. Cache de aplicação: o mais comum em desenvolvimento, usando Redis ou Memcached para armazenar resultados de queries, resultados de cálculos caros, sessões de usuário e dados frequentemente acessados. Cache do banco de dados: a maioria dos bancos tem cache de query internamente, armazenando resultados de consultas executadas recentemente. Cada nível agrega uma camada de proteção e performance, e um sistema bem arquitetado usa todos eles de forma complementar.

Redis na prática

O cache em memória mais popular, com estruturas de dados ricas e alta performance.

Redis e o servidor de cache em memória mais usado no mundo. Diferente de caches simples de chave-valor, o Redis suporta strings, listas, sets, sorted sets, hashes e streams, o que o torna adequado para uma variedade de casos de uso. Na prática, em uma aplicação web, você usária Redis para: armazenar o resultado de queries pesadas do banco com TTL (Time To Live) de alguns minutos; armazenar sessões de usuário para escalar horizontalmente sem perder o estado; implementar rate limiting por IP; gerenciar filas de tarefas em background; armazenar dados frequentemente acessados como listas de categorias, configurações e tokens de autenticação. Com latência de submilissegundo e suporte a persistência, o Redis tornou-se uma peça fundamental da infraestrutura de praticamente todo sistema web de escala.

Exemplo prático: cache de queries no e-commerce

Página de categorias com milhares de produtos cacheable por minutos.

Em um e-commerce, a página de listagem de uma categoria pode retornar milhares de produtos com suas imagens, preços e avaliações. Essa query com joins e ordenação pode levar 500ms no banco de dados. Sem cache, cada usuário que abre a página espera 500ms e gera carga no banco. Com cache: na primeira requisição, o resultado da query e armazenado no Redis com TTL de 5 minutos. As próximas requisições (que podem ser milhares em 5 minutos) retornam o cache em menos de 2ms. O banco e consultado apenas quando o cache expira. Em um e-commerce com 10 mil usuários simultâneos em uma promoção, essa diferença e a que determina se o site fica de pe ou cai. O desafio e invalidar o cache quando os dados mudam, como quando o preço de um produto e alterado.

Estrategias de invalidação de cache

A parte mais difícil do caching: saber quando e como invalidar dados desatualizados.

Phil Karlton, engenheiro da Netscape, disse que existem apenas dois problemas difíceis em ciência da computação: invalidação de cache e nomes de variáveis. Exagerando, mas a invalidação e de fato o maior desafio. As principais estrategias são: TTL (Time-To-Live): o cache expira automaticamente após um tempo definido, simples mas pode servir dados desatualizados até a expiração. Cache Aside (Lazy Loading): a aplicação verifica o cache primeiro; se não encontrar, busca no banco e armazena no cache. Write Through: quando escreve no banco, escreve também no cache simultaneamente, mantendo-os sempre sincronizados. Write Behind (Write Back): escreve no cache primeiro e no banco de forma assíncrona, mais rápido mas com risco de perda de dados. Cache Invalidation Explícita: quando o dado muda, a aplicação explicitamente remove ou atualiza a entrada no cache. Cada estrategia tem seu lugar dependendo da frequência de atualização e da tolerância a dados levemente desatualizados.

Cache distribuído e consistência

Em sistemas distribuídos, múltiplas instâncias precisam ver o mesmo estado do cache.

Em sistemas com múltiplas instâncias de aplicação (vários servidores rodando o mesmo código), cache local em memória seria inconsistente: cada instância teria seu próprio cache desatualizado. A solução e o cache distribuído, como o Redis, onde todas as instâncias compartilham o mesmo cache central. Um problema clássico e o thundering herd ou cache stampede: quando o cache expira, múltiplas requisições simultâneas encontram o cache vazio e vao ao banco de dados ao mesmo tempo, gerando uma sobrecarga massiva. Soluções incluem lock distribuído (apenas uma requisição busca do banco enquanto as outras aguardam), staggered expiration (adicionar jitter aleatório ao TTL para evitar expiração simultanea) e background refresh (renovar o cache antes de expirar).

Quando usar cache

Dados frequentemente lidos, raramente modificados e tolerantes a inconsistência temporária.

Cache e mais eficaz para dados que são lidos com muito mais frequência do que são escritos (alto read-to-write ratio), que são caros de calcular ou buscar (joins complexos, cálculos pesados, chamadas a APIs externas), que podem tolerar um nível de desatualização temporária (alguns minutos ou segundos), e que são acessados por muitos usuários simultaneamente. Casos clássicos: listas de categorias em e-commerce, resultados de busca, perfis de usuário, configurações do sistema, feeds de redes sociais, dados de catálogo de produtos, e resultados de queries de relatorio. Dados que precisam de consistência absoluta em tempo real, como saldo bancário ou estoque crítico, devem ser buscados diretamente do banco de dados.

Cuidados e anti-patterns

Cache cheio, vazamento de dados sensíveis e cache de dados mutalveis são armadilhas comuns.

Os erros mais comuns com cache incluem: armazenar dados sensíveis (senhas, dados pessoais) em cache compartilhado sem criptografia; definir TTL muito longo para dados que mudam com frequência, servindo informações desatualizadas; não monitorar o hit rate do cache (se estiver abaixo de 70%, o cache não esta sendo eficiente); usar chaves de cache não únicas, causando colisões entre contextos diferentes (ex: dois usuários com a mesma chave acessando dados um do outro); e não implementar fallback quando o cache esta indisponível, tornando o cache um ponto de falha crítico em vez de uma otimização. O cache deve ser tratado como uma otimização, nunca como o armazenamento principal de dados.

Resumo final

Cache bem implementado e uma das melhorias de performance mais impactantes em qualquer sistema.

Cache e uma das técnicas de performance mais fundamentais e impactantes em sistemas de software. Ao armazenar resultados de operações caras e reutiliza-los, o sistema consegue responder mais rápido, suportar mais carga com a mesma infraestrutura e reduzir custos operacionais. O desafio principal e a invalidação: saber quando e como atualizar o cache quando os dados subjacentes mudam. Com Redis como cache distribuído, estrategias bem definidas de invalidação e monitoramento continuo do hit rate, um sistema com caching bem implementado consegue multiplicar sua capacidade de atendimento sem escalar o banco de dados proporcionalmente. E um dos investimentos de performance com melhor custo-beneficio disponível.

Tutoriais em Video

Conceitos-chave

TTL (Time-To-Live)

Tempo de vida de uma entrada no cache, após expirar, o dado e removido e buscado novamente na origem

Cache Hit

Quando a requisição encontra o dado no cache, sem precisar ir ao banco de dados

Cache Miss

Quando o dado não esta no cache, o sistema vai a origem e armazena no cache para a próxima vez

Cache Aside

Estrategia onde a aplicação verifica o cache primeiro e, se não encontrar, busca na origem e armazena

Eviction Policy

Política de remoção quando o cache esta cheio: LRU (menos recente), LFU (menos frequente), etc.

Thundering Herd

Cache stampede: quando o cache expira e múltiplas requisições simultaneas vao ao banco ao mesmo tempo

Cache no Instagram

@bytebytego

Reels, Cache

@bytebytego

Cache no Facebook

Cache no X (Twitter)

@bytebytego

Cache strategies: quando usar cada uma

Ver post completo no X →
@bytebytego

Redis vs Memcached: diferenças na prática

Ver post completo no X →
@bytebytego

Thundering herd: o problema de cache que derruba sistemas

Ver post completo no X →
@bytebytego

Cache invalidation: a parte mais difícil

Ver post completo no X →
@bytebytego

Hit rate: como medir a eficiência do seu cache

Ver post completo no X →
@bytebytego

Cache distribuído com Redis em produção

Ver post completo no X →

O que devs dizem

Bruno L. ★★★★★

Adicionamos Redis para cachear as queries mais pesadas do nosso SaaS. A latência media da API caiu de 450ms para 40ms. O banco de dados foi de 90% de CPU para 15%. Com a mesma infraestrutura, conseguimos multiplicar por 10 o número de usuários atendidos.

Natalia K. ★★★★☆

A parte mais trabalhosa foi definir estrategias de invalidação para cada tipo de dado. Dados de catálogo com TTL de 10 minutos. Dados de preço com invalidação explícita quando o preço muda. Dados de sessão sem expiração automática. Cada caso exigiu uma estrategia diferente.

Cesar A. ★★★★★

Durante a Black Friday, nosso site de e-commerce sobreviveu a um pico 40x acima do normal porque o Redis absorveu praticamente todo o tráfego de leitura. O banco de dados mal foi consultado. O investimento de uma semana para implementar o caching corretamente pagou com juros em um único evento.