Estratégia de Caching: Redis, CDN, Cache do Navegador e Cache Invalidation
Uma Estratégia de Caching bem desenhada é um dos caminhos mais diretos para reduzir latência, economizar recursos e aumentar a resiliência de plataformas digitais.
Ao mesmo tempo, cache é uma fonte comum de incidentes: conteúdo desatualizado, inconsistência entre sistemas, falhas de autenticação, vazamento de dados e picos de carga quando o cache expira (cache stampede).
Este guia organiza o tema por camadas — CDN, cache do navegador e Redis — e fecha com o componente mais sensível: cache invalidation (invalidação de cache). A ideia é sair da teoria e chegar em decisões práticas e verificáveis.
1) O que é uma Estratégia de Caching (e por que “só ligar cache” falha)
Cache não é apenas “guardar uma resposta para reutilizar depois”. Em arquitetura moderna, cache envolve:
- Escopo: quem pode ver o conteúdo (público, usuário, tenant, região).
- Camada: navegador, CDN, edge, aplicação, banco.
- Política de expiração: TTL, revalidação, stale-while-revalidate.
- Chave de cache: como diferenciar variações (path, query, headers, cookies).
- Invalidação: quando e como descartar versões antigas.
- Controles de segurança: impedir cache de conteúdo sensível em lugar errado.
Uma Estratégia de Caching falha quando não define claramente o que pode e o que não pode ser cacheado, além de ignorar como as versões serão renovadas sem quebrar o usuário ou expor dados.
2) As camadas principais: Browser Cache, CDN e Redis
Pense em cache como uma hierarquia:
- Browser Cache (cliente): mais perto do usuário, custo quase zero por requisição repetida.
- CDN/Edge Cache: próximo geograficamente, reduz tráfego e acelera conteúdo público.
- Cache na aplicação (Redis/Memcached): reduz carga no banco e em serviços internos; acelera páginas e APIs dinâmicas.
- Cache no banco / query cache (quando aplicável): última linha; depende do SGBD.
A coordenação entre camadas é o que separa um ganho sustentável de um conjunto de “gambiarras” difíceis de operar.
3) Cache do navegador: controle fino com Cache-Control, ETag e versionamento
Quando usar
- Assets estáticos: JS, CSS, imagens, fontes.
- Conteúdo público com baixa criticidade: páginas institucionais.
- Respostas de API idempotentes em alguns cenários (com muito cuidado).
Regras práticas (passo a passo)
-
Para assets com versionamento no nome (hash)
Exemplo:app.3a9f2c1.js
Use cache agressivo:Cache-Control: public, max-age=31536000, immutable
-
Para HTML e conteúdo que muda com frequência
Evite “cache eterno”:Cache-Control: no-cache(permite armazenar, mas exige revalidação)- e utilize
ETagouLast-Modifiedpara revalidação eficiente (304 Not Modified)
-
Para conteúdo sensível (painéis, dados do usuário, páginas autenticadas) Em geral:
Cache-Control: no-store
Armadilhas comuns
- Cachear por engano conteúdo autenticado quando a resposta varia por cookie/token.
- Não variar por header (por exemplo,
Accept-Language) e entregar idioma errado. - Service Worker: pode sobrepor regras e manter conteúdo “preso” no cliente. Se houver, trate o SW como parte formal da estratégia.
4) CDN: aceleração e redução de origem sem perder controle
CDNs fazem cache na borda (edge) e podem também aplicar WAF, rate limiting e mitigação de DDoS. Mas o ganho de performance vem com uma exigência: definir bem a chave de cache e a política de expiração.
Quando usar
- Conteúdo público (assets, imagens, páginas estáticas).
- APIs públicas ou sem personalização por usuário (ou com variações explícitas e seguras).
- Conteúdo pesado (vídeo, downloads) com alto custo de origem.
Checklist prático para CDN
-
Defina o que é cacheável
- Assets: quase sempre.
- HTML: às vezes (com TTL curto ou revalidação).
- API: somente se não houver personalização por usuário ou se a variação estiver corretamente isolada (por exemplo, por
Authorizationnunca deve gerar cache público).
-
Defina a chave de cache
- Inclua: path e query relevantes.
- Inclua headers necessários (ex.:
Accept-Encoding,Accept-Language) viaVary. - Evite incluir cookies em cache público (isso fragmenta cache e pode vazar dados).
-
Use políticas modernas
- TTL adequado ao risco: mais curto para conteúdo dinâmico.
stale-while-revalidatequando suportado: entrega uma versão “não tão nova” enquanto revalida em background.
-
Purge com critério
- Invalidação total é cara e pode causar pico na origem.
- Prefira purgar por prefixo/rota ou por tags (quando a CDN suporta cache tags).
Aspecto de segurança (essencial)
- Nunca permita que respostas com
Set-Cookieou conteúdo autenticado sejam cacheadas publicamente. - Garanta separação por host/tenant quando há múltiplos domínios e ambientes.
- Monitore headers de resposta (incluindo
Cache-Control,Vary,Surrogate-Control) para evitar comportamento inesperado.
5) Redis como cache de aplicação: padrões confiáveis (Cache-Aside e afins)
Redis é muito usado para cache de dados e resultados de computações. A vantagem é reduzir a carga no banco e evitar recomputações. A desvantagem é introduzir consistência eventual e complexidade operacional.
Padrão mais comum: Cache-Aside (Lazy Loading)
Passo a passo:
- A aplicação tenta ler do Redis usando uma chave determinística.
- Se existir (cache hit), retorna.
- Se não existir (cache miss), busca no banco/serviço.
- Salva no Redis com TTL.
- Retorna a resposta.
Pontos críticos:
- TTL: sem TTL, chaves podem acumular e nunca atualizar.
- Serialização: padronize JSON/MessagePack/Protobuf e versões de schema.
- Tamanho: evite valores gigantes; prefira granularidade (por item) quando fizer sentido.
Outros padrões relevantes
- Write-through: ao escrever no banco, escreve no cache; reduz misses pós-escrita, aumenta acoplamento.
- Write-behind: escreve no cache e persiste depois; arriscado, exige fila e garantias.
- Read-through: biblioteca/carregador central gerencia misses; bom para consistência do acesso.
Cuidado com “cache de sessão”
Guardar sessão em Redis é comum, mas não confunda:
- Sessão (autenticação/estado): requisitos de segurança e expiração rigorosos.
- Cache (otimização): pode ser descartável.
Misturar conceitos leva a incidentes quando o cache expira e “derruba” autenticação ou perde estado crítico.
6) Cache Invalidation: a parte mais difícil (e onde nascem incidentes)
Invalidação é o mecanismo que evita servir dados antigos além do aceitável. Existem três estratégias principais, que podem ser combinadas:
6.1) TTL (expiração por tempo)
- Simples e robusto.
- Aceita que o dado pode ficar “velho” por até
TTL. - Bom para conteúdos com tolerância a atraso (ex.: contadores, rankings, catálogos com atualização não crítica).
Risco: inconsistência em janelas curtas e cache stampede quando muitas chaves expiram ao mesmo tempo.
Mitigações:
- Jitter: TTL com variação aleatória (ex.: 300s ± 30s).
- Stale-while-revalidate: servir o stale e atualizar em background.
- Lock de recomputação: um processo recalcula, outros aguardam ou recebem stale.
6.2) Invalidação por evento (event-driven)
- Quando um dado muda, emite evento e invalida chaves relacionadas.
- Melhor consistência, menor janela de stale.
- Exige bom mapeamento “dado → chaves” e uma infraestrutura de eventos (fila, stream).
Boas práticas:
- Use cache tags (quando disponível) para invalidar grupos (ex.: “produto:123”).
- Mantenha uma tabela de dependências ou uma convenção previsível de chaves.
Risco: eventos perdidos ou duplicados.
Mitigação: consumidores idempotentes e mecanismos de retry.
6.3) Versionamento de chaves (namespace/version key)
Em vez de apagar milhões de chaves, você muda a “versão”:
- Chave antiga:
product:123:v7 - Nova:
product:123:v8
Na prática, você armazena uma chave de versão por entidade ou por conjunto:
product:123:version = 8e compõe a chave real com ela.
Vantagens:
- Invalidação instantânea (muda a versão).
- Evita operações caras de delete/purge em massa.
Custo:
- Lixo residual até expirar (garanta TTL nas chaves versionadas).
7) Como escolher TTLs e políticas sem “chutar”
Uma Estratégia de Caching baseada em fatos depende de métricas. Três perguntas guiam TTL e invalidation:
- Qual é o impacto do dado desatualizado?
- Preço e estoque: impacto alto → TTL curto + evento/versão.
- Catálogo geral: impacto médio → TTL moderado + revalidação.
- Conteúdo institucional: impacto baixo → TTL longo.
-
Com que frequência muda?
- Muito frequente: cache pode perder eficiência; foque em agregações e páginas.
- Pouco frequente: cache agressivo com invalidação por evento.
-
Qual é o custo de recomputar?
- Alto custo: prefira stale-while-revalidate e proteção anti-stampede.
- Baixo custo: TTL menor e simplicidade.
8) Observabilidade e segurança: o que monitorar para não “operar no escuro”
Métricas essenciais
- Cache hit ratio por camada (browser/CDN/Redis).
- Latência p95/p99 antes e depois do cache.
- Taxa de erro (especialmente timeouts na origem quando CDN falha).
- Evictions no Redis (indica pressão de memória).
- Top keys e distribuição de TTL.
Controles de Cyber Segurança
- Dados sensíveis: use
Cache-Control: no-storequando aplicável. - Separação por usuário/tenant: chaves devem incluir identificadores corretos; nunca “reaproveitar” uma resposta autenticada como se fosse pública.
- Proteção contra cache poisoning:
- Normalize e valide headers/query que entram na chave de cache.
- Evite cachear respostas para requests com headers não confiáveis que alteram conteúdo.
- Logs e auditoria: registre decisões de cache (hit/miss, TTL aplicado, variante) para investigar inconsistências.
Conclusão
Uma Estratégia de Caching eficaz combina camadas (browser, CDN e Redis), define políticas claras (TTL, revalidação, stale-while-revalidate) e trata cache invalidation como parte do design — não como correção posterior. Em termos operacionais, o objetivo é acelerar sem perder controle: garantir consistência dentro do nível de risco aceitável, evitar vazamentos de dados e reduzir o impacto de picos e falhas.
Quando a estratégia está madura, cache deixa de ser “truque de performance” e vira uma disciplina: com regras explícitas, métricas, rotinas de invalidação e segurança incorporada desde o início.