1

Log groups "Never expire": o que sobrevive quando você apaga uma Lambda e a retenção por conta que a AWS lançou esta semana

A nota sobre o que sobrevive a uma VM tem um primo serverless: o log group. Quando uma função Lambda é invocada pela primeira vez, o CloudWatch cria /aws/lambda/<nome> com retenção "Never expire", e quando você apaga a função esse log group não vai junto. A documentação do Lambda diz isso em uma linha: "Log groups aren't deleted automatically when you delete a function". Em 9 de novembro a AWS publicou a política de retenção por conta, a primeira forma de colocar um vencimento em todos de uma vez. Tudo o que segue sai de docs.aws.amazon.com e da página de preços; as fontes estão no final.

Por que fica em "Never expire"

O CloudWatch guarda os eventos de log indefinidamente, a menos que alguém defina uma retenção; no console esse estado se chama "Never Expire". O Lambda cria o log group para você, na primeira invocação, com esse valor. Um stack do Terraform que declara a função mas não o log group deixa um recurso que o Terraform nunca teve no state: terraform destroy apaga a função e o log group continua lá, com seus bytes e sua linha na fatura. É o mesmo mecanismo de um disco criado fora do plano.

Encontrá-los: sem retenção e ordenados por bytes

describe-log-groups devolve retentionInDays só quando existe retenção; se o grupo nunca expira, o campo não vem. Isso permite filtrá-los com JMESPath comparando com null, e storedBytes diz quanto cada um pesa:

# log groups sem retenção, os mais pesados primeiro (a CLI v2 pagina sozinha)
aws logs describe-log-groups --output table \
  --query "reverse(sort_by(logGroups[?retentionInDays==null].{name:logGroupName,storedBytes:storedBytes,class:logGroupClass},&storedBytes))"

# só os do Lambda
aws logs describe-log-groups --log-group-name-prefix /aws/lambda \
  --query "logGroups[?retentionInDays==null].[logGroupName,storedBytes]" --output text

# funções que existem hoje, para cruzar com a lista anterior
aws lambda list-functions --query "Functions[].FunctionName" --output text

Um log group /aws/lambda/x sem uma função x na segunda lista é um órfão: a função foi apagada e os logs ficaram. E os que têm função mas não têm retenção são o outro problema: crescem todo mês.

Quanto custa

Em us-east-1, a classe Standard cobra US$ 0,50 por GB ingerido e US$ 0,03 por GB-mês armazenado (comprimido); a classe Infrequent Access, US$ 0,25 por GB ingerido e US$ 0,018 por GB-mês. O nível gratuito cobre 5 GB. O armazenamento é o que se acumula: 100 GB que ninguém lê são US$ 3 por mês para sempre, e uma função barulhenta que loga cada request pode deixar várias centenas de GB antes de alguém olhar.

Retenção por log group

# um log group
aws logs put-retention-policy --log-group-name /aws/lambda/minha-funcao --retention-in-days 30

# todos os do Lambda sem retenção, para 30 dias
for g in $(aws logs describe-log-groups --log-group-name-prefix /aws/lambda \
  --query "logGroups[?retentionInDays==null].logGroupName" --output text); do
  aws logs put-retention-policy --log-group-name "$g" --retention-in-days 30
done

Os valores aceitos são fixos: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1096, 1827, 2192, 2557, 2922, 3288 e 3653 dias. Os eventos vencidos podem levar até 72 horas para serem apagados. No Terraform, um aws_cloudwatch_log_group com retention_in_days e o nome /aws/lambda/<função> declarado antes da função mantém o grupo no state, e skip_destroy = true o preserva de propósito em um destroy.

Retenção por conta: a novidade de 9 de novembro

A política de retenção por conta define uma retenção para todos os log groups da região ou para um subconjunto por prefixo de nome, e escolhe se vale para os existentes ou só para os novos. Para os do Lambda:

aws logs put-account-policy \
  --policy-name LambdaRetentionPolicy \
  --policy-type RETENTION_POLICY \
  --policy-document '{"retentionInDays": 90, "enforcementMode": "RETROACTIVE"}' \
  --selection-criteria 'LogGroupNamePrefix="/aws/lambda"'

# com --dry-run mostra a quais grupos se aplicaria sem criar nada
  • enforcementMode: RETROACTIVE alcança os grupos que já existem e os novos; NEW_ONLY, só os criados depois.
  • O mínimo é 30 dias; o máximo, 3653, ou NEVER_EXPIRE. Até 20 políticas por região, e se várias coincidem vence a de retenção mais longa.
  • A política de conta substitui a retenção do log group, mesmo quando a do grupo era mais longa. Leva 24 horas para ser aplicada.
  • Sem custo adicional. Não disponível no Bahrein nem nos Emirados.

O que a política não faz é apagar o log group: um órfão com retenção de 90 dias para de acumular bytes e em três meses pesa zero, mas continua listado. Para sumir é preciso aws logs delete-log-group, e o melhor é fazer isso com a lista cruzada acima, não com um for sobre tudo que está em /aws/lambda/.

Fontes

  • AWS Lambda Developer Guide, "Working with the Lambda logging and log groups" ("By default, CloudWatch automatically creates a log group named /aws/lambda/…") e "Logging in Node.js" ("Log groups aren't deleted automatically when you delete a function").
  • Amazon CloudWatch Logs User Guide, "Working with log groups and log streams" (retenção indefinida por padrão, "Never Expire", políticas de retenção por conta com o exemplo de put-account-policy).
  • AWS What's New, 9 de novembro de 2026, "Amazon CloudWatch Logs now supports account-level log retention policies"; referência da CLI logs put-account-policy (RETROACTIVE / NEW_ONLY, mínimo de 30 dias, 20 políticas, 24 horas, substitui a do grupo).
  • Referência da CLI: logs put-retention-policy (valores aceitos, exclusão até 72 horas depois) e logs describe-log-groups (retentionInDays ausente quando nunca expira, storedBytes).
  • Amazon CloudWatch Pricing, US East (N. Virginia): US$ 0,50 e US$ 0,25 por GB ingerido, US$ 0,03 e US$ 0,018 por GB-mês, 5 GB grátis.
  • Terraform Registry, aws_cloudwatch_log_group (retention_in_days, skip_destroy); hashicorp/terraform-provider-aws, issue #454 ("When you delete the lambda, it doesn't delete anything from CloudWatch").

Escrevo sobre infraestrutura no blog do Control Cloud, onde trabalho; a versão original desta nota está em https://controlcloud.dev/pt/blog/cloudwatch-log-groups-never-expire-lambda-borrada-retencion-por-cuenta?utm_source=tabnews&utm_medium=referral&utm_campaign=tabnews-cwlogs

Carregando publicação patrocinada...