trilha

System Design/02 - Componentes/Caching2 min

Client Caching

Perguntas-guia
  • Que problema isso resolve?
  • Quando usar / quando NÃO usar?
  • Qual o principal trade-off?
  • Como isso falha em produção?

Conceito

Cache no próprio cliente — navegador, app móvel, SDK. É o cache mais rápido possível porque elimina a rede inteira.

Headers HTTP que controlam

Header Efeito
Cache-Control: max-age=3600 Válido por 1 hora, sem perguntar
Cache-Control: no-cache Pode guardar, mas revalide antes de usar
Cache-Control: no-store Nunca guarde (dado sensível)
Cache-Control: private Só o navegador; proxies e CDN não
ETag / If-None-Match Revalidação: 304 Not Modified, sem corpo
Last-Modified / If-Modified-Since Idem, por data
immutable Nunca revalide — para conteúdo versionado

Outros armazenamentos do cliente

localStorage e IndexedDB (persistentes), sessionStorage (por aba), Service Worker (controle programático, offline-first), e cache em memória do app.

Trade-offs

O ganho é absoluto: latência zero e carga zero no servidor.

O custo é que você perde o controle. Uma vez que o cliente guardou com max-age=86400, não existe forma de invalidar — nenhum purge alcança o navegador do usuário. Ele vai usar o dado velho pelo tempo que você declarou.

Isso torna o versionamento de URL essencial: app.a3f9c1.js com max-age=31536000, immutable é seguro precisamente porque o nome muda quando o conteúdo muda. Já app.js com um ano de cache é uma decisão que você não pode desfazer.

Dado sensível merece atenção especial: sem no-store, uma resposta com informação pessoal pode ficar no disco do cliente, acessível a quem usar a máquina depois.

E há o problema da diversidade: você não controla as versões de navegador nem as políticas de cache dos intermediários. Comportamento que funciona num ambiente pode divergir em outro.

Exemplo prático

Estratégia de cache de um SPA:

index.html      → no-cache          (revalida sempre; é o índice)
app.a3f9c1.js   → max-age=31536000, immutable
estilo.7b2e.css → max-age=31536000, immutable
/api/*          → no-store          (dado do usuário)

O index.html é pequeno e revalida a cada visita — normalmente devolvendo 304. Quando há deploy, ele muda e passa a referenciar app.9d4f2b.js, um nome que o cliente nunca viu e que vai buscar.

Resultado: deploy propaga imediatamente, e todos os assets pesados vêm do disco local. O usuário baixa alguns bytes em vez de megabytes.

Relacionado


Parte de Caching · roadmap.sh/system-design

Buscar

Busca por título, seção e texto das notas