CDN
Servidores perto do usuário para entregar arquivos e respostas sem chegar à sua aplicação.
As decisões sobre a CDN são quatro: o que colocar na borda, como invalidar, como montar a chave do cache e como proteger os dados pessoais.
O que colocar na borda
| Conteúdo | Cabeçalhos | Por quê |
|---|---|---|
Arquivos com nome versionado (app.3f9a2c.js) | public, max-age=31536000, immutable | O nome muda a cada versão; o arquivo nunca muda |
| Imagens e mídia enviadas | public, max-age=86400 ou mais, com versão no caminho | Mudam pouco |
| Páginas públicas (produto, artigo, vitrine) | public, s-maxage=60 a 300, stale-while-revalidate, stale-if-error | A CDN guarda por minutos; o navegador, por pouco tempo |
| API pública (catálogo, preços, configurações) | public, s-maxage de segundos a minutos | Alivia a origem nos picos |
| Páginas e API com dados do usuário | private, no-store ou private, max-age curto | Nunca num cache compartilhado |
Respostas de escrita (POST, PUT) | Não são guardadas | Por definição |
O padrão para páginas públicas separa os dois prazos: max-age curto, para o navegador buscar de novo logo, e s-maxage maior, para a CDN, que a origem pode invalidar quando quiser. O stale-while-revalidate evita que o primeiro usuário depois do vencimento espere pela origem, e o stale-if-error mantém o site no ar se a origem cair, como mediu o teste.
Como invalidar
| Estratégia | Como funciona | Quando usar |
|---|---|---|
| Nome versionado | O arquivo novo tem outro nome; o HTML aponta para ele | Arquivos estáticos: nunca precisa invalidar |
| Prazo curto | A cópia vence sozinha em segundos ou minutos | Conteúdo que tolera alguns minutos de atraso |
| Limpeza pela API da CDN (purge) | A aplicação pede para apagar um caminho quando o conteúdo muda | Mudanças que precisam aparecer logo |
| Etiquetas de cache (surrogate keys, cache tags) | Cada resposta leva etiquetas (produto-7, categoria-tenis); a limpeza é por etiqueta | Uma mudança que afeta muitas páginas |
Revalidação com ETag | A CDN pergunta à origem se a versão mudou; a origem responde 304 sem corpo | Reduz o tráfego da origem sem servir conteúdo velho por muito tempo |
A combinação mais robusta é prazo moderado com limpeza por etiqueta quando o conteúdo muda: se a limpeza falhar, a cópia vence sozinha.
A chave do cache
A chave decide o que conta como "a mesma resposta". Por padrão, é a URL completa.
| Ajuste | Por quê |
|---|---|
Tirar parâmetros de rastreamento (utm_*, fbclid, gclid) | No teste, cinco utm_source diferentes deram cinco MISS |
| Ordenar os parâmetros | ?a=1&b=2 e ?b=2&a=1 são a mesma busca |
Vary só com o necessário | Vary: Accept-Encoding é normal; Vary: Cookie ou Vary: User-Agent fragmentam o cache em milhares de cópias |
Idioma e moeda na URL (/pt-BR/...) em vez de cookie | A versão de cada idioma fica no cache sem depender do cookie |
Proteger os dados pessoais
| Risco | Defesa |
|---|---|
Uma rota com dados do usuário marcada como public | private, no-store explícito em toda resposta autenticada; nunca depender do padrão |
Um middleware que aplica public a todas as rotas | Cabeçalhos definidos por rota, com teste automatizado das rotas autenticadas |
| A CDN configurada para "guardar tudo" ignorando os cabeçalhos | Regras da CDN que respeitam o Cache-Control da origem; exceções só para caminhos públicos conhecidos |
| Cookies de sessão em páginas públicas | Não criar sessão para visitantes anônimos; o cookie também impede o cache, como mostrou o teste |
O teste do nível Conceito mostrou o incidente completo: com public, o Bruno recebeu a conta da Ana. Um teste automatizado que pede uma rota autenticada e confere private ou no-store no Cache-Control evita esse tipo de regressão.
A borda como camada da aplicação
As CDNs atuais vão além do cache:
| Recurso | Para quê |
|---|---|
| TLS e HTTP/3 na borda | O aperto de mão acontece perto do usuário |
| Proteção contra ataques (DDoS, WAF) | O tráfego malicioso para na borda |
| Limite de requisições | Antes de chegar à origem, como mostra o tópico de limite de requisições |
| Funções na borda (Workers, Lambda@Edge) | Redirecionamentos, testes A/B, autenticação simples perto do usuário |
| Proteção da origem (origin shield) | Uma camada intermediária que junta os MISS de todas as bordas antes de chegar à origem |
Resumo da decisão
- Arquivos estáticos com nome versionado e cache de um ano,
immutable. - Páginas e API públicas com
s-maxage,stale-while-revalidateestale-if-error. - Respostas com dados do usuário sempre com
private, no-store, testadas. - Sem cookies em respostas públicas e sem parâmetros de rastreamento na chave do cache.
- Invalidação por prazo moderado e limpeza por etiqueta.
ETagpara revalidar sem reenviar o corpo.
O próximo nível mostra a origem com os cabeçalhos certos nas cinco linguagens, testada atrás de uma borda.
Prompts para aprofundar
Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.
Planejar a CDN do meu sistema
Quero colocar uma CDN na frente do meu sistema. Pergunte quais tipos de conteúdo existem (estáticos, páginas, API), quais dependem do usuário, com que frequência mudam e qual CDN eu pretendo usar. Proponha, para cada tipo de conteúdo, os cabeçalhos Cache-Control, a estratégia de invalidação e os ajustes da chave do cache. No final, liste o que precisa mudar na aplicação (cookies, cabeçalhos por rota, nomes versionados).
Invalidação de cache na CDN
Preciso que mudanças de conteúdo apareçam logo, mesmo com cache na CDN. Pergunte qual CDN eu uso, que conteúdo muda, com que frequência e quantas páginas uma mudança afeta. Compare para o meu caso: prazo curto, limpeza por caminho, limpeza por etiqueta (surrogate keys) e revalidação com ETag. Mostre como emitir as etiquetas nas respostas e como disparar a limpeza a partir da aplicação.
Usar a CDN para proteger a origem
Quero que a CDN segure o meu sistema em picos de acesso e se a origem cair. Pergunte quais rotas recebem mais tráfego, quais podem servir conteúdo de alguns minutos atrás e qual CDN eu uso. Explique: cache curto em rotas de API públicas, stale-while-revalidate, stale-if-error, proteção da origem (origin shield), limite de requisições e proteção contra ataques na borda. Monte a configuração para o meu caso.