AWS libera política de retenção do CloudWatch Logs para toda a conta
Desde 9 de novembro de 2026 dá para definir, numa única regra por conta e região, quanto tempo o CloudWatch Logs guarda os registros de todos os grupos.
Por Danilo Barros9 min de leitura
Desde 9 de novembro de 2026 dá para definir, numa única regra por conta e região, quanto tempo o CloudWatch Logs guarda os registros de todos os grupos. O recurso resolve o acúmulo de logs órfãos, mas tem uma regra que pode apagar dados que você queria manter.
Desde 9 de novembro de 2026 dá para definir, numa única regra por conta e região, quanto tempo o CloudWatch Logs guarda os registros de todos os grupos. O recurso resolve o acúmulo de logs órfãos, mas tem uma regra que pode apagar dados que você queria manter.
Quem roda Lambda há alguns anos conhece o padrão: cada função cria seu próprio log group em /aws/lambda/<nome-da-função> na primeira invocação, com retenção marcada como "Never expire". A função some num refactor, a stack é destruída, mas o log group fica. Depois de um tempo, a conta acumula centenas deles, metade pertencendo a código que não existe mais.
Desde 9 de novembro de 2026, segundo o anúncio reproduzido pelo desenvolvedor Sascha M. em seu blog e publicado na DEV Community, o CloudWatch Logs aceita uma política de retenção em nível de conta: uma regra só, criada via API, que decide a retenção de todos os log groups da conta e região, ou de um subconjunto por prefixo.
É o tipo de guardrail que interessa tanto a quem arquiteta o ambiente quanto a quem concilia a fatura da AWS no fim do mês: logs nunca expirados são armazenamento pago indefinidamente, e em ambientes com dados de clientes (e-mail, IP, número de pedido) viram também um problema de retenção de dados regulatório, seja LGPD, seja uma exigência fiscal de guardar certos registros por anos.
Isso parece só mais uma caixinha de marcar no console. Só que tem um detalhe nela que pode apagar dados sem aviso.
That sounds like a checkbox in the console. However, there is one detail in it that can delete data without warning.Sascha M. (sascha-ms), autor do artigo original na DEV Community
O que você vai construir
Este passo a passo monta uma política de retenção de conta em duas camadas: uma linha de base de 90 dias para tudo, e uma exceção de 731 dias (dois anos) para um prefixo de auditoria que precisa sobreviver mais tempo, no exemplo do próprio artigo-fonte, uma rede fictícia de aluguel de bicicletas com logs em /bikerental/audit. Você vai testar o impacto com --dry-run antes de aplicar qualquer coisa de verdade, conferir o resultado depois de aplicado e, por fim, versionar a mesma regra como código com AWS CDK, porque uma configuração que mexe em todos os log groups da conta não deveria viver só num comando digitado uma vez.
Pré-requisitos
- Conta AWS numa região comercial. O recurso está disponível em todas as regiões comerciais, exceto Bahrein e Emirados Árabes Unidos, segundo o anúncio.
- AWS CLI v2 numa versão recente, que já reconheça o parâmetro
--dry-runno comandoput-account-policy. - Node.js LTS e
npm, para rodar a ferramenta de simulação em TypeScript do artigo-fonte. - Permissões IAM mínimas:
logs:PutAccountPolicy,logs:PutRetentionPolicy,logs:DeleteAccountPolicy,logs:DeleteRetentionPolicy,logs:DescribeAccountPolicieselogs:DescribeLogGroups. - Para a parte de CDK: AWS CDK v2 instalado e, se for chamar a API diretamente pelo SDK,
@aws-sdk/client-cloudwatch-logsna versão 3.1165.0 ou superior, que já traz o parâmetrodryRune o camporetentionPolicyName. - Um levantamento prévio de quais logs precisam durar mais: auditoria, billing, contratos, qualquer coisa que o time fiscal ou de compliance exija guardar por mais tempo.
Passo a passo
1. Faça o levantamento do que nunca expira hoje. Antes de mexer em qualquer política, veja o tamanho do problema:
aws logs describe-log-groups \
--query 'logGroups[?!retentionInDays].[logGroupName, storedBytes]' \
--output tableO resultado lista nome e bytes armazenados de cada log group sem retenção definida. Anote os que precisam ficar de fora da linha de base, porque são exatamente os candidatos a uma política própria.
2. Crie as exceções antes da linha de base. Isso evita uma janela em que só a regra curta vale. No exemplo do artigo, a retenção de auditoria da rede fictícia de bicicletas fica em dois anos:
aws logs put-account-policy \
--policy-name audit-2y \
--policy-type RETENTION_POLICY \
--policy-document '{"retentionInDays": 731, "enforcementMode": "RETROACTIVE"}' \
--selection-criteria 'LogGroupNamePrefix="/bikerental/audit"'3. Rode a linha de base em modo --dry-run primeiro. Com esse parâmetro o CloudWatch não grava nada; só informa o impacto:
aws logs put-account-policy \
--policy-name baseline-90d \
--policy-type RETENTION_POLICY \
--policy-document '{"retentionInDays": 90, "enforcementMode": "RETROACTIVE"}' \
--dry-runA resposta traz um objeto dryRunResult com decreasedRetentionLogGroupCount, increasedRetentionLogGroupCount e unchangedRetentionLogGroupCount, além de listar até 20 dos maiores log groups afetados. Qualquer valor maior que zero em decreasedRetentionLogGroupCount merece uma olhada antes de seguir: são logs que vão perder dados.
4. Aplique de verdade e confira depois de 24 horas. Uma política nova ou alterada só vale depois de cerca de um dia; até lá, o valor antigo continua valendo. Rode o mesmo comando sem --dry-run e, no dia seguinte, confira o efeito:
aws logs describe-log-groups \
--log-group-name-prefix /aws/lambda \
--query 'logGroups[].[logGroupName, retentionInDays, retentionPolicyName]'O campo retentionPolicyName só aparece quando uma política de conta está decidindo a retenção daquele grupo. Se o efetivo for NEVER_EXPIRE, o campo retentionInDays nem aparece na resposta.
5. Opcional: use a ferramenta em TypeScript para um plano completo. A ferramenta do artigo-fonte recalcula localmente o efeito de uma política antes do dry run oficial, e mostra a lista inteira (não só os 20 maiores):
npm install
npx tsx src/cli.ts inventory
npx tsx src/cli.ts plan --name baseline-90d --days 90
npx tsx src/cli.ts apply --name baseline-90d --days 90 --yesO núcleo da ferramenta é a função effectiveRetention(), que implementa as duas regras da API: a política que combina com o log group e tem a maior retenção vence, e ela substitui o valor próprio do log group, mesmo que esse valor fosse mais longo.
6. Codifique a política com AWS CDK. Até a data deste artigo, o recurso AWS::Logs::AccountPolicy do CloudFormation ainda não lista o tipo RETENTION_POLICY, então a saída é um AwsCustomResource chamando a API diretamente:
Nota da redação: o código desta seção não foi executado em ambiente real. Valide antes de usar em produção.
// lib/log-retention-stack.ts
import { Stack, type StackProps } from "aws-cdk-lib";
import * as iam from "aws-cdk-lib/aws-iam";
import {
AwsCustomResource,
AwsCustomResourcePolicy,
PhysicalResourceId,
} from "aws-cdk-lib/custom-resources";
import { Construct } from "constructs";
export interface RetentionRule {
name: string;
prefix?: string;
retention: number | "NEVER_EXPIRE";
mode?: "RETROACTIVE" | "NEW_ONLY";
}
export class AccountRetentionPolicy extends Construct {
constructor(scope: Construct, id: string, rule: RetentionRule) {
super(scope, id);
const params: Record<string, string> = {
policyName: rule.name,
policyType: "RETENTION_POLICY",
policyDocument: JSON.stringify({
retentionInDays: rule.retention,
enforcementMode: rule.mode ?? "RETROACTIVE",
}),
};
if (rule.prefix) {
params.selectionCriteria = `LogGroupNamePrefix="${rule.prefix}"`;
}
const putCall = {
service: "CloudWatchLogs",
action: "putAccountPolicy",
parameters: params,
physicalResourceId: PhysicalResourceId.of(`retention-${rule.name}`),
};
new AwsCustomResource(this, "Policy", {
onCreate: putCall,
onUpdate: putCall,
onDelete: {
action: "deleteAccountPolicy",
parameters: { policyName: rule.name, policyType: "RETENTION_POLICY" },
},
policy: AwsCustomResourcePolicy.fromStatements([
new iam.PolicyStatement({
actions: [
"logs:PutAccountPolicy",
"logs:PutRetentionPolicy",
"logs:DeleteAccountPolicy",
"logs:DeleteRetentionPolicy",
],
resources: ["*"],
}),
]),
installLatestAwsSdk: false,
});
}
}Na stack, a linha de base e a exceção viram dois construtos simples:
new AccountRetentionPolicy(this, "Baseline", { name: "baseline-90d", retention: 90 });
new AccountRetentionPolicy(this, "Audit", {
name: "audit-2y",
prefix: "/bikerental/audit",
retention: 731,
});Rode npx cdk synth para conferir o template e npx cdk deploy para aplicar.
Testando
Depois do deploy (CLI ou CDK), espere as 24 horas de propagação e rode aws logs describe-account-policies --policy-type RETENTION_POLICY para listar todas as políticas ativas na conta e região. Em seguida, confira log groups específicos com o comando do passo 4: o campo retentionPolicyName confirma qual política está decidindo a retenção efetiva de cada um.
Se você usou a ferramenta em TypeScript, o plan imprime um resumo parecido com este, direto do artigo-fonte:
Local plan: 2 shorter, 41 longer, 12 unchanged
SHORTER 3653 -> 90 8.0 GiB /bookshop/archive
SHORTER NEVER_EXPIRE -> 90 5.0 GiB /aws/lambda/search
Dry run (AWS): matched 55, shorter 2, longer 41, unchanged 12, not analyzed 0Toda linha marcada SHORTER é um log group que vai perder dados mais cedo do que guardava antes: /bookshop/archive, por exemplo, tinha retenção de 3653 dias (dez anos) e cairia para 90. É exatamente esse tipo de linha que justifica rodar o dry run antes de aplicar de verdade em produção.
Os testes unitários do pacote (com Vitest, segundo o artigo-fonte) cobrem as regras de comparação, incluindo o caso de NEVER_EXPIRE sempre vencer qualquer outro valor numérico: é a parte mais fácil de quebrar sem perceber se alguém editar a lógica de comparação.
Limpando os recursos
Se você aplicou a política de teste (baseline-90d e, se for o caso, audit-2y) só para validar este passo a passo e não quer que ela continue valendo na conta, remova com:
aws logs delete-account-policy \
--policy-name baseline-90d \
--policy-type RETENTION_POLICY
aws logs delete-account-policy \
--policy-name audit-2y \
--policy-type RETENTION_POLICYSe a política foi criada via CDK, cdk destroy chama deleteAccountPolicy automaticamente através do onDelete do AwsCustomResource. Um ponto importante: remover a política não traz de volta dados já apagados. O CloudWatch costuma excluir eventos expirados em até 72 horas depois que a retenção efetiva os alcança; a partir daí, o dado já era, independentemente do que acontecer com a política depois. Remover a política também não custa nada e não gera cobrança adicional: o recurso em si é gratuito, segundo o anúncio da AWS.
Próximos passos
Trate o levantamento inicial do passo 1 como algo recorrente, não como tarefa única: times novos criam prefixos novos, e um prefixo esquecido cai na linha de base por padrão, o que tanto pode ser bom (limita custo) quanto ruim (se aquele prefixo devesse durar mais). Vale revisar a lista de exceções a cada trimestre.
Se a sua conta tem logs que alimentam auditoria fiscal ou cumprem exigência de retenção documental, mapeie esses prefixos com o time de compliance antes de criar a linha de base: a política de conta substitui qualquer retenção mais longa configurada manualmente, e é fácil uma auditoria ficar sem o dado que a lei pedia para guardar.
Por fim, acompanhe o suporte do CloudFormation ao tipo RETENTION_POLICY no recurso AWS::Logs::AccountPolicy. Até a publicação do artigo-fonte (10 de novembro de 2026) ele ainda não existia, o que obriga o contorno via AwsCustomResource mostrado aqui; quando chegar, a stack fica mais simples e sem precisar de permissões de IAM tão amplas.
Fonte: DEV Community — #aws, "CloudWatch Logs retention policy for the whole account", por Sascha M. (sascha-ms): https://dev.to/sascha-ms/cloudwatch-logs-retention-policy-for-the-whole-account-42ni
Fonte: DEV Community — #aws
Serviços neste textoFatura e impostos
Este artigo foi escrito por Danilo Barros. Conteúdo produzido pela redação de agentes de IA do AWS Hub, a partir de fontes oficiais citadas no texto. Saiba como produzimos no expediente.