Cache HTTP permite que navegadores, CDNs e proxies reutilizem respostas sem consultar ou transferir novamente todo o conteúdo. Em aplicações Node.js, configurar corretamente Cache-Control, Vary, validadores e políticas por tipo de recurso reduz latência, banda e carga no servidor.
Cache incorreto pode vazar dados privados, servir conteúdo antigo ou criar inconsistências difíceis de diagnosticar. A política deve ser explícita para páginas públicas, APIs autenticadas, arquivos versionados e respostas personalizadas.
Cache-Control
O cabeçalho principal é:
Cache-Control: public, max-age=300Diretivas comuns:
public: caches compartilhados podem armazenar;private: somente cache privado do cliente;no-cache: pode armazenar, mas deve revalidar;no-store: não armazenar;max-age: frescor no cliente;s-maxage: frescor em cache compartilhado;must-revalidate: não usar resposta expirada sem validação;immutable: recurso versionado não mudará durante o frescor;stale-while-revalidate: permite stale enquanto atualiza;stale-if-error: permite stale durante falha.
Resposta pública
res.setHeader(
'cache-control',
'public, max-age=60, s-maxage=300, stale-while-revalidate=60',
);O navegador considera 60 segundos; um CDN pode considerar 300. Depois, pode servir conteúdo stale por uma janela enquanto revalida.
Resposta privada
res.setHeader('cache-control', 'private, no-cache');Isso permite armazenamento privado com revalidação. Para dados extremamente sensíveis, use no-store, mas não aplique indiscriminadamente.
no-cache não significa sem cache
no-cache permite armazenar, mas exige validação antes de reutilizar. no-store é a diretiva que pede para não armazenar.
Arquivos versionados
Arquivos com hash no nome podem receber cache longo:
Cache-Control: public, max-age=31536000, immutableQuando o conteúdo muda, o build gera outro nome:
app.a1b2c3.js
app.d4e5f6.jsNão use um ano de cache em URL que será sobrescrita.
HTML
HTML costuma precisar de política curta ou revalidação, pois aponta para os assets atuais:
Cache-Control: no-cacheAssim, o navegador pode armazenar e validar rapidamente.
APIs públicas
Uma API de catálogo pode ser cacheada:
app.get('/api/products/:id', async (req, res) => {
const product = await repository.findById(req.params.id);
res.setHeader(
'cache-control',
'public, max-age=30, s-maxage=300, stale-if-error=600',
);
res.json(product);
});Garanta que a resposta não varia por usuário ou autorização.
APIs autenticadas
Respostas com dados do usuário não devem entrar em cache compartilhado por engano. Use:
Cache-Control: private, no-cacheOu no-store quando a política exigir.
Authorization
Respostas a requisições com Authorization possuem regras especiais em caches compartilhados. Não tente habilitar cache público sem entender o padrão e garantir que o conteúdo seja realmente igual para todos.
Vary
Vary informa quais cabeçalhos alteram a representação:
Vary: Accept-Encoding, Accept-LanguageSem Vary, um cache pode servir idioma ou compressão incorreta. Porém, variar por muitos cabeçalhos reduz hit rate.
Não use Vary: Cookie sem necessidade
Cookies frequentemente são únicos por usuário, o que destrói cache compartilhado. Separe conteúdo público e personalizado em endpoints diferentes.
ETag
ETag identifica uma versão. O cliente revalida com If-None-Match. Se não mudou, o servidor retorna 304 sem corpo.
Last-Modified
Last-Modified: Wed, 01 Oct 2026 12:00:00 GMTO cliente usa If-Modified-Since. Datas têm precisão limitada e podem ser menos confiáveis que ETag, mas são úteis para arquivos.
Resposta 304
Uma resposta 304 não possui corpo, mas deve manter cabeçalhos relevantes de cache, como Cache-Control, ETag e Vary.
Expires
Expires define uma data absoluta. Cache-Control é mais flexível e preferido. Expires pode ser usado por compatibilidade.
CDN
Uma CDN pode cachear por URL, query, headers e cookies. Configure:
- cache key;
- TTL;
- purge;
- stale;
- proteção de conteúdo privado;
- normalização de query;
- variação por encoding.
Cache key
Parâmetros irrelevantes, como tracking, podem reduzir hit rate. Mas remover parâmetros que alteram conteúdo causa respostas erradas. Defina explicitamente.
Query strings
Alguns caches tratam toda query como parte da chave. Normalize ordem e allowlist quando possível.
Cookies
Respostas que definem Cookie podem ser consideradas privadas por infraestrutura. Evite Set-Cookie em assets públicos.
Surrogate-Control
Alguns CDNs aceitam cabeçalhos específicos para controlar apenas a borda, deixando Cache-Control para o navegador. Verifique o provedor.
stale-while-revalidate
Permite servir uma versão antiga por curto período enquanto uma atualização ocorre. Isso reduz latência e stampede, mas usuários podem ver conteúdo desatualizado.
stale-if-error
Durante falhas, um cache pode servir resposta antiga. É excelente para catálogos e conteúdo público, mas inadequado para saldo, estoque crítico ou autorização.
Invalidação
Estratégias:
- TTL curto;
- URL versionada;
- purge por URL;
- tags de surrogate;
- evento de atualização;
- revalidação condicional.
Invalidação perfeita em todos os níveis é difícil. Escolha tolerância a stale por recurso.
Cache stampede
Quando uma resposta popular expira, milhares de requisições podem atingir o backend. Use stale-while-revalidate, request coalescing, lock e jitter de TTL.
Jitter
const ttlSeconds = 300 + Math.floor(Math.random() * 60);Isso distribui expirações de várias chaves.
Cache no processo
Um Map local é rápido, mas cada processo possui estado diferente e perde dados no restart. Use somente para cache pequeno, limitado e descartável.
Cache e compressão
Uma resposta pode ter variantes Gzip e Brotli. Envie Vary: Accept-Encoding e garanta que o CDN armazene corretamente.
Cache e CORS
Quando Access-Control-Allow-Origin varia por Origin, adicione Vary: Origin. Ou use uma origem fixa.
HEAD
Requisições HEAD podem verificar metadados sem corpo. O servidor deve produzir cabeçalhos equivalentes ao GET.
Range requests
Vídeos e arquivos grandes podem usar Range. Cache parcial exige suporte correto de CDN e cabeçalhos como Accept-Ranges e Content-Range.
Erros
Não cacheie 500 por padrão por períodos longos. Alguns caches armazenam status negativos como 404; use TTL curto e intencional.
Negative caching
Cachear 404 por segundos pode proteger banco de buscas repetidas. Mas após criar o recurso, usuários podem continuar vendo 404 até expirar.
Observabilidade
Meça:
- cache hit e miss;
- age;
- revalidações;
- 304;
- bytes economizados;
- stale servido;
- purges;
- latência por status de cache;
- origem acessada.
Headers de diagnóstico
CDNs costumam adicionar headers como Age e indicadores próprios. Não exponha detalhes sensíveis. Use-os para diagnóstico interno.
Teste
Teste primeira resposta, resposta fresca, expirada, 304, conteúdo alterado, idioma, compressão, usuário autenticado, purge e falha da origem.
curl -i http://localhost:3000/api/products/42
curl -i http://localhost:3000/api/products/42Erros comuns
- usar public em resposta privada;
- confundir no-cache e no-store;
- não enviar Vary;
- cachear URL sem versão por um ano;
- variar por Cookie desnecessariamente;
- não manter cabeçalhos em 304;
- purge sem autenticação;
- usar stale em dados críticos;
- não medir cache hit;
- duplicar cache sem estratégia.
Fluxo recomendado
Classifique cada resposta como pública, privada ou não armazenável. Use URLs versionadas para assets, revalidação para HTML e TTLs curtos com stale para APIs públicas. Combine com Compressão HTTP, Rate Limiting, Circuit Breaker e métricas em Prometheus.
Consulte o guia de cache HTTP da MDN e a especificação HTTP Caching.



