These rules find CloudWatch log groups and streams that accumulate cost without being actively used, bounded by a retention policy, or monitored with metric filters.
| Rule ID | Scan Type | Name |
|---|---|---|
| CLDBRN-AWS-CLOUDWATCH-1 | Discovery and IaC | CloudWatch Log Group Missing Retention |
| CLDBRN-AWS-CLOUDWATCH-2 | Discovery | CloudWatch Log Group Inactive |
| CLDBRN-AWS-CLOUDWATCH-3 | Discovery | CloudWatch Log Group No Metric Filters |
CLDBRN-AWS-CLOUDWATCH-1
CloudWatch Log Group Missing Retention
Scan type: Discovery and IaC
What it checks
Flags CloudWatch log groups that have no retention policy set. Without a retention period, log data is stored indefinitely and you are billed for all accumulated storage.
Log groups in the DELIVERY delivery class are excluded because they are managed by AWS and cannot have retention configured by users.
Why it matters
CloudWatch Logs storage costs $0.03 per GB per month. Log groups without retention can grow without bound, especially for high-volume services like VPC Flow Logs, API Gateway access logs, or Lambda functions. A log group running for a year without retention can accumulate hundreds of gigabytes before anyone notices.
What triggers a finding
retentionInDays is undefined AND the log group class is not DELIVERY.
How to remediate
Set a retention period on the log group. Choose a value that meets your compliance requirements — common values are 7, 14, 30, 90, or 365 days. You can set retention via the AWS Console, CLI, or your IaC tool:
aws logs put-retention-policy \
--log-group-name /your/log-group \
--retention-in-days 30
IaC resources checked
| Provider | Resource |
|---|---|
| Terraform | aws_cloudwatch_log_group |
| CloudFormation | AWS::Logs::LogGroup |
CLDBRN-AWS-CLOUDWATCH-2
CloudWatch Log Group Inactive
Scan type: Discovery
What it checks
Flags CloudWatch log groups whose most recent stream has no observed event history or whose latest stream activity is more than 90 days old. The rule evaluates at the log group level, not individual streams.
Log groups in the DELIVERY delivery class are excluded because they are managed by AWS.
Why it matters
Inactive log groups accumulate storage costs without providing operational value. Log groups that stop receiving data become dead weight, and teams often forget they exist. Reviewing or removing stale log groups prevents unbounded storage spend.
What triggers a finding
Either of the following conditions on the log group's most recent stream activity:
- Both
lastEventTimestampandlastIngestionTimeareundefined(no stream in the log group has ever received events) - The most recent of
lastEventTimestampandlastIngestionTimeis older than 90 days
How to remediate
Review the log group and either delete it if no longer needed, or set a retention policy to limit storage costs:
aws logs delete-log-group \
--log-group-name /your/inactive-log-group
If the log group is still needed but inactive, set a short retention period to reclaim storage:
aws logs put-retention-policy \
--log-group-name /your/log-group \
--retention-in-days 7
CLDBRN-AWS-CLOUDWATCH-3
CloudWatch Log Group No Metric Filters
Scan type: Discovery
What it checks
Flags CloudWatch log groups storing at least 1 GB of data when they define no metric filters. Large log groups without metric filters suggest logs are being stored without active monitoring or processing.
Why it matters
CloudWatch Logs charges $0.50/GB ingested and $0.03/GB-month stored. A log group accumulating gigabytes of data without any metric filters means you're paying to store logs you may not be using for alerting or operational insights. Adding metric filters or reducing retention can cut storage costs.
What triggers a finding
storedBytes >= 1,073,741,824 (1 GiB) AND metricFilterCount is 0.
How to remediate
Define metric filters to extract operational metrics, or set a shorter retention period to limit storage costs. If the log group is genuinely unused, consider deleting it entirely.
See Also
- CLI discover command — scan live CloudWatch resources
- SDK Reference — run discovery programmatically