DevGuideTK

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údoCabeçalhosPor quê
Arquivos com nome versionado (app.3f9a2c.js)public, max-age=31536000, immutableO nome muda a cada versão; o arquivo nunca muda
Imagens e mídia enviadaspublic, max-age=86400 ou mais, com versão no caminhoMudam pouco
Páginas públicas (produto, artigo, vitrine)public, s-maxage=60 a 300, stale-while-revalidate, stale-if-errorA CDN guarda por minutos; o navegador, por pouco tempo
API pública (catálogo, preços, configurações)public, s-maxage de segundos a minutosAlivia a origem nos picos
Páginas e API com dados do usuárioprivate, no-store ou private, max-age curtoNunca num cache compartilhado
Respostas de escrita (POST, PUT)Não são guardadasPor 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égiaComo funcionaQuando usar
Nome versionadoO arquivo novo tem outro nome; o HTML aponta para eleArquivos estáticos: nunca precisa invalidar
Prazo curtoA cópia vence sozinha em segundos ou minutosConteú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 mudaMudanças que precisam aparecer logo
Etiquetas de cache (surrogate keys, cache tags)Cada resposta leva etiquetas (produto-7, categoria-tenis); a limpeza é por etiquetaUma mudança que afeta muitas páginas
Revalidação com ETagA CDN pergunta à origem se a versão mudou; a origem responde 304 sem corpoReduz 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.

AjustePor 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árioVary: 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 cookieA versão de cada idioma fica no cache sem depender do cookie

Proteger os dados pessoais

RiscoDefesa
Uma rota com dados do usuário marcada como publicprivate, no-store explícito em toda resposta autenticada; nunca depender do padrão
Um middleware que aplica public a todas as rotasCabeçalhos definidos por rota, com teste automatizado das rotas autenticadas
A CDN configurada para "guardar tudo" ignorando os cabeçalhosRegras 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úblicasNã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:

RecursoPara quê
TLS e HTTP/3 na bordaO 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çõesAntes 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

  1. Arquivos estáticos com nome versionado e cache de um ano, immutable.
  2. Páginas e API públicas com s-maxage, stale-while-revalidate e stale-if-error.
  3. Respostas com dados do usuário sempre com private, no-store, testadas.
  4. Sem cookies em respostas públicas e sem parâmetros de rastreamento na chave do cache.
  5. Invalidação por prazo moderado e limpeza por etiqueta.
  6. ETag para 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.