CDN e cache
CDN resolve três problemas ao mesmo tempo: latência (o conteúdo fica perto de quem pede), carga (a origem para de servir o que se repete) e custo (saída pela CDN costuma ser mais barata que saída direta da região). Para quem atende o Brasil inteiro a partir de São Paulo, a diferença de latência para o Norte e Nordeste é grande o suficiente para aparecer nas métricas de negócio.
O preço é um novo lugar onde as coisas ficam desatualizadas — e quase todo problema de CDN é, no fundo, um problema de chave de cache.
Cache-Control: quem manda é a origem
Seção intitulada “Cache-Control: quem manda é a origem”A CDN obedece aos cabeçalhos que a sua aplicação envia. Configure na origem:
# asset com nome versionado (app.9f3a2c.js) — cacheie forte e para sempreCache-Control: public, max-age=31536000, immutable
# HTML que muda: revalide sempre, mas permita servir enquanto revalidaCache-Control: public, max-age=0, s-maxage=60, stale-while-revalidate=300
# conteúdo por usuário: nunca em cache compartilhadoCache-Control: private, no-storeTrês diretivas que resolvem a maior parte dos casos:
s-maxagevale só para o cache compartilhado (CDN), independente domax-agedo navegador. É o que permite cache longo na borda e curto no cliente.stale-while-revalidateserve a versão antiga enquanto busca a nova — o usuário nunca espera pela origem.stale-if-errorcontinua servindo o conteúdo velho quando a origem cai. É disponibilidade de graça: ative.
Chave de cache
Seção intitulada “Chave de cache”A chave define o que conta como “a mesma resposta”. Por padrão é a URL — e os problemas começam quando a resposta varia por algo que não está nela.
- Query string:
?utm_source=...cria uma entrada nova para cada campanha e destrói a taxa de acerto. Ignore parâmetros de rastreamento na chave. - Cabeçalhos: se a resposta muda por idioma ou dispositivo, declare
Vary: Accept-Language.Vary: User-Agentfragmenta o cache em milhares de variantes — evite. - Cookie: um cookie de sessão presente na requisição costuma desabilitar o cache inteiro. Separe o domínio dos assets estáticos, ou configure a CDN para ignorar cookies em caminhos estáticos.
O erro grave a evitar: servir de um cache compartilhado uma página que contém dado de um
usuário. Isso vaza informação de uma pessoa para outra. Toda resposta autenticada precisa
de Cache-Control: private, no-store — e vale testar isso explicitamente.
curl -sI https://loja.exemplo.com.br/app.9f3a2c.js | grep -iE 'cache-control|age|x-cache'# x-cache: HIT/MISS (o nome varia por CDN) diz se veio da bordaInvalidação e versionamento
Seção intitulada “Invalidação e versionamento”Invalidação global é lenta, às vezes cobrada, e é a solução errada para o caso comum.
Prefira versionar o nome do arquivo: app.9f3a2c.js muda de nome a cada build, então
nunca precisa ser invalidado, e o navegador nunca serve o antigo.
Guarde a invalidação para o que não pode ser versionado — HTML de entrada, sitemap.xml,
uma imagem substituída às pressas:
aws cloudfront create-invalidation --distribution-id E123 --paths '/index.html' '/'E invalide caminhos específicos: /* esvazia tudo, faz a origem receber uma avalanche
de requisições e pode derrubar o serviço no momento seguinte.
Proteja a origem
Seção intitulada “Proteja a origem”Se a origem responde direto na internet, alguém vai encontrá-la e passar por cima da CDN — inclusive um ataque. Feche o caminho:
- Aceite tráfego apenas dos IPs da CDN, ou exija um cabeçalho secreto compartilhado.
- Use origem privada quando o provedor suportar (OAC/Origin Access, Private Link).
- Ative coalescing de requisições (a CDN faz uma só requisição à origem para muitos pedidos simultâneos do mesmo objeto) — é o que evita a estampida quando um item popular expira.
- Deixe a CDN aplicar limite de taxa e WAF antes da origem.
Cachear conteúdo dinâmico, com cuidado
Seção intitulada “Cachear conteúdo dinâmico, com cuidado”Dá para cachear resposta de API e HTML dinâmico, e o ganho é grande — desde que:
- A resposta seja igual para todo mundo naquele contexto (produto, categoria, home deslogada).
- O TTL seja curto (5 a 60 segundos) e combinado com
stale-while-revalidate. - Exista invalidação por tag/
surrogate-keyquando o dado muda, para não esperar o TTL. - Nada autenticado ou personalizado entre no cache compartilhado.
Um TTL de 10 segundos na home costuma cortar a maior parte do tráfego da origem em pico — poucas coisas em operação têm essa relação custo-benefício.
Por fim, monitore a taxa de acerto por caminho. Queda súbita quase sempre significa
mudança de chave de cache (um parâmetro novo, um cookie que passou a ser enviado, um
Vary acrescentado), e ela chega à origem como aumento de carga sem aumento de usuários.
Próximo passo: feche a trilha com o modelo de acesso que substitui o perímetro em Zero trust na prática.