Atualizando Conteúdo no CloudFront: Como Criar uma Invalidação para Limpar o Cache da Edge

Você substituiu um arquivo no S3, fez o deploy, abriu o navegador — e o CloudFront continua servindo a versão antiga. Esse é um dos problemas mais comuns em operações com CloudFront, e a solução passa por entender como a invalidação de cache do CloudFront funciona antes de sair clicando em botões.

TL;DR — Invalidação de Cache no CloudFront

SituaçãoAção Recomendada
Arquivo específico desatualizadoInvalidar o path exato: /imagens/logo.png
Múltiplos arquivos em um diretórioInvalidar com wildcard: /assets/*
Deploy completo do siteInvalidar tudo: /*
Evitar custo de invalidação recorrenteUsar versionamento de arquivo no nome (cache busting)

Como o Cache do CloudFront Funciona

O CloudFront opera com uma rede de pontos de presença (PoPs) distribuídos globalmente, chamados de edge locations. Quando um usuário requisita um objeto, o edge verifica se tem uma cópia em cache. Se tiver e o TTL ainda não expirou, ele serve direto — sem consultar o S3. Isso é exatamente o que você quer em produção para performance, e exatamente o que te atrapalha quando você precisa propagar uma mudança imediatamente.

O TTL de um objeto no edge é controlado pelos cabeçalhos Cache-Control e Expires que o S3 retorna, combinados com as configurações de TTL mínimo, padrão e máximo definidas no behavior da distribuição. Se o S3 não retornar esses cabeçalhos, o CloudFront usa o TTL padrão configurado no behavior — que por padrão é 86.400 segundos (24 horas).

Uma invalidação força o CloudFront a marcar os objetos em cache como expirados em todos os edge locations, fazendo com que a próxima requisição busque o conteúdo atualizado diretamente na origem.

sequenceDiagram participant U as Usuário participant E as Edge Location participant S3 as Amazon S3 Note over E: Cache válido (TTL não expirado) U->>E: GET /imagens/logo.png E-->>U: 200 OK (versão antiga do cache) Note over E: Invalidação criada e propagada U->>E: GET /imagens/logo.png E->>S3: Objeto expirado — busca na origem S3-->>E: 200 OK (versão nova) E-->>U: 200 OK (versão nova) Note over E: Nova versão armazenada em cache
  1. Requisição normal com cache válido: o edge serve o objeto diretamente sem contatar o S3.
  2. Após invalidação: o objeto é marcado como expirado no edge. A próxima requisição vai até o S3, busca o arquivo atualizado, e o edge armazena a nova versão em cache.
  3. Propagação: a invalidação se propaga para todos os edge locations da distribuição, não apenas para um PoP específico.

Criando uma Invalidação de Cache no CloudFront

A invalidação pode ser criada via Console, AWS CLI ou API. Em pipelines de CI/CD, o CLI é o caminho natural. Abaixo os dois métodos principais.

Via AWS Console

  1. Acesse o serviço CloudFront no Console AWS.
  2. Clique na distribuição desejada.
  3. Vá até a aba Invalidations.
  4. Clique em Create invalidation.
  5. Informe os paths desejados — um por linha. Use /* para invalidar tudo.
  6. Clique em Create invalidation e aguarde o status mudar para Completed.

Via AWS CLI

Para invalidar um arquivo específico:

aws cloudfront create-invalidation \
  --distribution-id E1EXAMPLE123456 \
  --paths '/imagens/logo.png'

Para invalidar múltiplos paths em uma única chamada:

aws cloudfront create-invalidation \
  --distribution-id E1EXAMPLE123456 \
  --paths '/index.html' '/assets/app.js' '/assets/style.css'

Para invalidar toda a distribuição:

aws cloudfront create-invalidation \
  --distribution-id E1EXAMPLE123456 \
  --paths '/*'

Para verificar o status da invalidação criada:

aws cloudfront get-invalidation \
  --distribution-id E1EXAMPLE123456 \
  --id INVALIDATION_ID

Para listar invalidações recentes de uma distribuição:

aws cloudfront list-invalidations \
  --distribution-id E1EXAMPLE123456

Permissões IAM Necessárias

A conta ou role que executa a invalidação precisa das seguintes permissões:

🔽 Clique para expandir — Política IAM mínima para invalidação
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontInvalidation",
      "Effect": "Allow",
      "Action": [
        "cloudfront:CreateInvalidation",
        "cloudfront:GetInvalidation",
        "cloudfront:ListInvalidations"
      ],
      "Resource": "arn:aws:cloudfront::123456789012:distribution/E1EXAMPLE123456"
    }
  ]
}

Substitua 123456789012 pelo seu Account ID e E1EXAMPLE123456 pelo ID real da sua distribuição. A ação cloudfront:ListDistributions requer "Resource": "*" — verifique o Service Authorization Reference para confirmar o suporte a resource-level por ação antes de restringir.

Diagnóstico: Por Que o Arquivo Ainda Aparece Desatualizado Após a Invalidação?

Aqui é onde a maioria das pessoas perde tempo. A invalidação foi criada, o status está Completed, mas o navegador ainda mostra o arquivo antigo. Antes de criar outra invalidação, vale verificar cada camada do problema.

graph TD A["Arquivo desatualizado
no CloudFront"] --> B{"S3 tem o arquivo
atualizado?"}; B -- Não --> C["Refaça o upload
para o S3"]; B -- Sim --> D{"Invalidação está
Completed?"}; D -- InProgress --> E["Aguarde a propagação"]; D -- Completed --> F{"curl retorna
conteúdo correto?"}; F -- Não --> G{"Path da invalidação
bate exatamente?"}; G -- Não --> H["Crie nova invalidação
com path correto"]; G -- Sim --> I["Verifique MinTTL
no behavior"]; F -- Sim --> J["Problema é cache
local do navegador"]; J --> K["Limpe o cache
do navegador"];

Passo 1 — Confirme que o arquivo no S3 realmente foi atualizado

Parece óbvio, mas em pipelines com múltiplos estágios é comum o upload falhar silenciosamente ou sobrescrever o bucket errado. Verifique o ETag e o LastModified do objeto diretamente:

aws s3api head-object \
  --bucket meu-bucket-exemplo \
  --key imagens/logo.png

Compare o ETag retornado com o hash do arquivo local. Se forem iguais, o upload não aconteceu.

Passo 2 — Verifique se a invalidação foi concluída com sucesso

Uma invalidação no estado InProgress ainda não propagou para todos os edge locations. O tempo de propagação varia — consulte a documentação oficial para valores atuais. Confirme o status:

aws cloudfront list-invalidations \
  --distribution-id E1EXAMPLE123456 \
  --query 'InvalidationList.Items[*].{ID:Id,Status:Status,CreateTime:CreateTime}' \
  --output table

Passo 3 — Descarte o cache do navegador antes de concluir qualquer coisa

O cache do navegador é independente do cache do CloudFront. Um arquivo com Cache-Control: max-age=3600 pode estar armazenado localmente por até uma hora, mesmo após a invalidação no edge ter sido concluída. Teste com curl para eliminar essa variável:

curl -I https://d1example.cloudfront.net/imagens/logo.png

Observe o cabeçalho X-Cache na resposta. O valor Hit from cloudfront indica que o edge ainda está servindo do cache. O valor Miss from cloudfront indica que a requisição foi até a origem. Se o curl retorna o conteúdo correto mas o navegador não, o problema é local.

Passo 4 — Verifique o path da invalidação contra o path real do objeto

Invalidações são case-sensitive e precisam corresponder exatamente ao path do objeto na distribuição, incluindo query strings se a distribuição estiver configurada para encaminhar e cachear por query string. Um path /Imagens/Logo.png não invalida /imagens/logo.png. Confirme os paths dos objetos no S3 e compare com o que foi enviado na invalidação.

Pense no path de invalidação como uma chave de cache exata. O CloudFront não faz correspondência parcial nem normaliza capitalização. Se o path não bater bit a bit com o que está em cache, a invalidação passa em branco.

Passo 5 — Verifique se há um behavior com TTL mínimo alto sobrepondo a invalidação

Esse é o cenário que mais gera confusão. Se o behavior da distribuição tiver um Minimum TTL configurado com um valor alto, o CloudFront pode ignorar o cabeçalho Cache-Control: no-cache da origem e manter o objeto em cache além do esperado. Uma invalidação limpa o cache atual, mas se a origem continuar retornando cabeçalhos que conflitam com o TTL mínimo do behavior, o objeto será recacheado com o TTL antigo na próxima requisição.

Verifique o TTL mínimo configurado no behavior:

aws cloudfront get-distribution-config \
  --id E1EXAMPLE123456 \
  --query 'DistributionConfig.DefaultCacheBehavior.{MinTTL:MinTTL,DefaultTTL:DefaultTTL,MaxTTL:MaxTTL}'

Se o MinTTL estiver em um valor alto, ajuste-o ou corrija os cabeçalhos de cache retornados pelo S3.

Cache Busting: A Alternativa Estrutural à Invalidação

Invalidações têm custo. A AWS oferece as primeiras 1.000 paths de invalidação por mês sem custo — após isso, há cobrança por path. Verifique os valores atuais na página de preços do CloudFront. Além do custo, invalidar /* em toda distribuição a cada deploy é uma abordagem que escala mal.

A alternativa operacionalmente mais robusta é o cache busting por versionamento de nome de arquivo: em vez de sobrescrever app.js, você publica app.v2.js ou app.a1b2c3d4.js (hash do conteúdo). O HTML referencia o novo nome, o CloudFront trata como um objeto diferente e busca da origem automaticamente. Nenhuma invalidação necessária.

Essa abordagem é padrão em frameworks modernos de frontend como Next.js, Vite e webpack, que geram hashes de conteúdo nos nomes dos assets automaticamente.

graph LR subgraph Invalidação A1["app.js"] -->|sobrescreve| A2["app.js"] A2 --> INV["Criar Invalidação
/app.js"] INV --> EDGE1["Edge atualizado"] end subgraph CacheBusting B1["app.a1b2c3.js"] -->|novo objeto| B2["app.d4e5f6.js"] B2 --> EDGE2["Edge busca automaticamente
objeto novo"] end

Invalidação de Cache no CloudFront em Pipelines de CI/CD

Em pipelines automatizados, a sequência correta é: upload dos arquivos para o S3 primeiro, invalidação depois. Inverter a ordem cria uma janela onde o CloudFront tenta buscar da origem um arquivo que ainda não chegou ao S3.

Exemplo de sequência em shell script para um pipeline:

🔽 Clique para expandir — Script de deploy com invalidação
#!/bin/bash
set -e

DISTRIBUTION_ID="E1EXAMPLE123456"
BUCKET="meu-bucket-exemplo"
BUILD_DIR="./dist"

echo "Fazendo upload dos arquivos para o S3..."
aws s3 sync "$BUILD_DIR" "s3://$BUCKET" \
  --delete \
  --cache-control "max-age=31536000,public" \
  --exclude "index.html"

aws s3 cp "$BUILD_DIR/index.html" "s3://$BUCKET/index.html" \
  --cache-control "no-cache,no-store,must-revalidate" \
  --content-type "text/html"

echo "Criando invalidação no CloudFront..."
INVALIDATION_ID=$(aws cloudfront create-invalidation \
  --distribution-id "$DISTRIBUTION_ID" \
  --paths '/index.html' \
  --query 'Invalidation.Id' \
  --output text)

echo "Invalidação criada: $INVALIDATION_ID"
echo "Aguardando conclusão da invalidação..."

aws cloudfront wait invalidation-completed \
  --distribution-id "$DISTRIBUTION_ID" \
  --id "$INVALIDATION_ID"

echo "Deploy concluído com sucesso."

O comando aws cloudfront wait invalidation-completed bloqueia a execução do pipeline até que a invalidação seja concluída, evitando que etapas subsequentes de smoke test rodem contra conteúdo ainda desatualizado.

Conclusão e Próximos Passos para Gerenciar Cache no CloudFront

Substituir um arquivo no S3 não é suficiente para atualizar o conteúdo servido pelo CloudFront — o cache da edge precisa ser explicitamente invalidado ou o objeto precisa ter um nome diferente. Para deploys pontuais, a invalidação via CLI é direta e eficaz. Para operações recorrentes, estruture seu pipeline com cache busting por hash de conteúdo e reserve invalidações para casos excepcionais.

Recursos oficiais para aprofundamento:

Glossário

TermoDefinição
Edge LocationPonto de presença do CloudFront onde o conteúdo é armazenado em cache e servido aos usuários finais.
InvalidaçãoOperação que marca objetos em cache no CloudFront como expirados, forçando a busca da versão atualizada na origem na próxima requisição.
TTL (Time to Live)Tempo em segundos que um objeto permanece válido no cache do edge antes de ser revalidado ou removido.
Cache BustingTécnica de incluir um hash ou versão no nome do arquivo para forçar o navegador e o CDN a tratarem o novo arquivo como um objeto diferente.
BehaviorRegra de configuração em uma distribuição CloudFront que define como requisições para um determinado path pattern são tratadas, incluindo TTL, métodos HTTP permitidos e política de cache.

Comentários

Postagens mais visitadas deste blog

Variáveis de Ambiente no Lambda: Configuração, Acesso e Criptografia com KMS

Entendendo Instâncias T3 Burstáveis: CPU Credits e Por Que Seu Servidor Fica Lento

Monitoramento de Memória RAM no EC2: Por que o CloudWatch Agent é Obrigatório