CloudWatch log groups with no retention policy that keep every log event forever
What does ZopNight detect here?
ZopNight flags CloudWatch Logs log groups with no retention setting (`put-retention-policy` never applied), because CloudWatch Logs keeps their log events indefinitely and storage bills at $0.03 per GB-month in us-east-1. Pricing the trim needs stored bytes broken down by age, which ZopNight does not collect yet, so no finding is raised today rather than a guessed figure.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-057 |
| Category | rightsizing |
| Severity | low |
| Metric | none — pure configuration read |
| Threshold | no retention policy (never expire) |
| Source | ZopNight |
| Permissions used | logs:DescribeLogGroups |
Where it applies
The default is to keep logs indefinitely
By default, CloudWatch Logs stores log data indefinitely. Nothing ages out until you set a retention period on the log group; once you do, data older than the setting is deleted, typically within 72 hours of reaching it. A log group that never gets a retention setting therefore grows every day it receives data, and the stored data is billed monthly. The current AWS price list for US East (N. Virginia) puts that storage at $0.03 per GB-month.
The cost creeps up slowly, which is why it gets missed. A group taking in a few GB a day holds terabytes after a couple of years, most of it logs nobody will ever query.
Finding groups set to never expire
aws logs describe-log-groups \ --query 'logGroups[?retentionInDays==null].[logGroupName,storedBytes]' \ --output tableThe retention field is absent from the output for groups that never expire, and storedBytes shows
how much each is holding. Sort by that column to see where the storage is.
The single check this rule makes
ZopNight reads the retention setting of every log group. A group with no retention, or a value of zero, is a candidate; a group with any positive retention period is left alone, however long it is. There is no metric, threshold or lookback window. This rule has nothing to say about how the logs arrive or what else reads them.
Why no finding is raised yet
Setting retention deletes only the data older than the new window, so the saving depends on how much stored data is older than, say, 90 days, and on how fast new data arrives. ZopNight does not yet collect stored bytes broken down by age or the group’s ingestion rate for this check. Rather than report a fraction of the log group’s bill, the rule stays silent until those measurements exist. Ingestion cost, a separate lever, is covered by CloudWatch Log Group Standard Class, Use Infrequent Access.
The storage saving once age data is available
saving = stored GB older than the new retention window x storage rate per GB-monthAt $0.03 per GB-month, every 100 GB that ages out saves $3 a month, every month after.
Setting a retention period
- Pick a period per group: many teams use 30 days for dev and test and 90 days for most production application logs.
- If older data must be kept, export it first with
aws logs create-export-taskand let an S3 lifecycle rule tier or expire it. AWS notes log data can take up to 12 hours to become available for export. - Apply the policy:
aws logs put-retention-policy --log-group-name /aws/lambda/my-fn --retention-in-days 90 - Set retention in the infrastructure code that creates the group, so a recreated group does not come back as never expire.