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:RETROACTIVEalcanç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) elogs describe-log-groups(retentionInDaysausente 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