Skip to main content
rightsizing · aws

CloudWatch log groups storing logs with no expiry

resource types
1
rule IDs covered
1
severity
low

What does ZopNight detect here?

CloudWatch Logs storage bills $0.03 per GB-month, and a log group whose retention_days is 0 or unset keeps every byte forever. ZopNight detects those groups but currently abstains from a savings claim: AWS reports only total stored bytes, never their age, so a trim figure cannot be computed honestly.

Signal and threshold

How ZopNight evaluates CloudWatch log groups storing logs with no expiry.
Field Value
Rule IDsRC-057
Categoryrightsizing
Severitylow
Metricnone — pure configuration read
Sourcecloudwatch_logs.go

Log groups that never expire anything

A CloudWatch log group created without a retention policy defaults to “never expire”. Every byte ever ingested stays, and stored data bills at $0.03 per GB-month indefinitely. Nothing self-corrects here: the group grows monotonically for as long as anything writes to it, which makes unbounded retention one of the quietest recurring costs in an AWS account.

What retention_days zero really means

The discoverer stamps each log group’s configured retention into metadata as retention_days, where 0 encodes never-expire. The rule suppresses only when a real policy above 0 is present; a value of 0 or a missing key both count as unbounded. An earlier version read retention from a tag the discoverer never wrote. The suppression branch was unreachable and the rule over-fired on every priced group regardless of its true setting. Reading the authoritative metadata fixed that.

Why no dollar figure is attached yet

The rule currently abstains on every group rather than publish a saving. The honest trim saving has two parts: stored gigabytes already older than the new window, plus the ongoing accumulation you stop paying for. Computing either needs the age distribution of stored bytes or an ingest rate, and AWS exposes neither. What AWS reports about a log group is one total storedBytes figure, with no age breakdown. Multiplying that total by the storage rate would over-count by every byte still inside the window, a fabricated number. A cost-driven recommendation must be concrete or silent, so until an age-bucketed producer exists, this one is silent.

Finding groups with unbounded retention

Terminal window
aws logs describe-log-groups \
--query 'logGroups[?retentionInDays==null].[logGroupName,storedBytes]' --output table

Groups with a large storedBytes and no retentionInDays are your ranked to-do list.

Choosing a retention window

Set retention deliberately: 90 days suits most production workloads, 30 days is plenty for dev and test, and anything with a compliance hold belongs in S3 via an export task, where storage classes are far cheaper than log storage. Applying a policy deletes data older than the window on a rolling basis, so agree the number with whoever owns the audit trail first.

See it fire on your bill.

Connect an account read-only. The first findings land in minutes.

417 rule families across 353 resource types on 22 platforms. Every threshold, metric, and IAM action is documented on these pages before you grant anything.

417 rule families documented
353 resource types covered
read-only default access level
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·