AWS CloudWatch Cost Optimization · Startup Guide
How to Reduce AWS CloudWatch Costs by 60–80%
CloudWatch log ingestion at $0.50/GB and unlimited retention are a silent budget drain for fast-growing startups. Most CloudWatch costs are avoidable with log level discipline, retention policies, and smarter query strategies.
CloudWatch Pricing Breakdown
| Cost item | Price | Notes |
|---|---|---|
| Log ingestion | $0.50/GB | Per GB of data ingested |
| Log storage | $0.03/GB/month | Per GB stored; with no retention = forever |
| Logs Insights query | $0.005/GB scanned | Charged for data scanned, not data returned |
| Custom metrics | $0.30/metric/month | First 10 metrics free |
| Dashboards | $3.00/dashboard/month | First 3 free |
| Alarms | $0.10/alarm/month | First 10 free |
| Contributor Insights | $0.50/rule + $0.02/1M events | Processing fee per log event |
4 CloudWatch Cost Optimizations
Start with log retention - it takes 30 minutes and stops unbounded growth immediately.
Set retention policies on all CloudWatch log groups
By default, CloudWatch log groups retain logs indefinitely. Every GB ingested stays forever at $0.03/GB/month - adding up silently over years. A startup ingesting 100GB/month with no retention policy accumulates 1,200GB/year of logs, costing $36/month just to store a year of logs that nobody reads.
How to implement
- List all log groups with no retention: aws logs describe-log-groups --query 'logGroups[?retentionInDays==null].logGroupName'
- Set retention to 30 days for application logs, 90 days for access logs, 365 days for audit/compliance logs
- AWS CLI: aws logs put-retention-policy --log-group-name /aws/lambda/my-function --retention-in-days 30
- For automation: use a Lambda or CloudFormation StackSet to enforce retention across all accounts
- Check existing groups with millions of stored events - deleting old log streams manually frees storage immediately
Note: This is a 30-minute fix that stops unbounded growth. Many startups we audit have log groups from 2–3 years ago still accumulating storage charges at full price.
Reduce log verbosity and filter before ingestion
CloudWatch charges $0.50/GB for log ingestion. Verbose logging (DEBUG level in production, logging every request/response body, logging individual DB queries) is the primary driver of high ingestion costs. Reducing log level to INFO or WARN and filtering noise before sending to CloudWatch cuts ingestion costs proportionally.
How to implement
- Set production Lambda and ECS log levels to INFO (not DEBUG) - typically reduces volume 50–80%
- Use Subscription Filters to send only ERROR/WARN logs to CloudWatch; route DEBUG to S3 via Kinesis Firehose
- For Lambda: disable CloudWatch logging for high-volume functions that don't need it - set LoggingConfig LoggingType: None
- For ALB access logs: send to S3 directly instead of CloudWatch (S3 storage is 60× cheaper than CloudWatch logs)
- Use EMF (Embedded Metrics Format) for Lambda metrics instead of creating high-cardinality custom metrics
Note: ALB access logs to CloudWatch is a common mistake. At $0.50/GB ingestion, a busy load balancer generating 1TB/month of access logs costs $500/month in CloudWatch - the same data in S3 costs $23/month.
Disable unused CloudWatch dashboards and Contributor Insights
Each CloudWatch custom dashboard costs $3/month. Each Contributor Insights rule costs $0.50/month + $0.02 per 1M log events processed. Most teams accumulate dashboards and rules created for one-time debugging sessions that never get cleaned up.
How to implement
- CloudWatch console → Dashboards → delete all unused/obsolete dashboards
- CloudWatch console → Contributor Insights → disable rules for log groups that no longer exist or are rarely viewed
- Review custom metrics: each unique metric with custom namespace costs $0.30/month
- High-resolution metrics (< 60s) cost 3× more - downgrade to standard resolution where sub-minute granularity isn't needed
Note: Small savings individually, but worth doing during a general cleanup. 50 unused dashboards = $150/month, 20 Contributor Insights rules processing 10M events/month = $4.50/month.
Switch from CloudWatch Logs Insights to Athena for ad-hoc queries
CloudWatch Logs Insights charges $0.005 per GB of data scanned. For teams querying large log volumes daily (security reviews, analytics, debugging), this accumulates quickly. Shipping logs to S3 and querying with Athena costs $5 per TB scanned - 100× cheaper than CloudWatch Logs Insights for the same data.
How to implement
- Create a CloudWatch Logs subscription filter to stream logs to Kinesis Firehose
- Configure Firehose to deliver to an S3 bucket with Parquet conversion enabled
- Create an Athena table over the S3 path with appropriate partitioning (year/month/day/hour)
- Query with Athena: $5/TB scanned vs. $0.005/GB = $5/TB for CloudWatch Logs Insights
- Keep CloudWatch Logs for real-time alerting; use Athena for historical analysis
Note: This architectural change takes a day to set up but pays back within weeks for teams running frequent ad-hoc log queries. The pipeline also enables long-term log archival to Glacier for compliance.
Frequently Asked Questions
Why is my CloudWatch bill so high?
Usually one of three things: log ingestion from verbose logging (DEBUG level in production, large request/response bodies), log storage from groups with no retention policy accumulating for years, or Logs Insights queries scanning large log volumes daily. Run Cost Explorer → Service: CloudWatch → Group by Usage Type to find the specific driver.
How do I set CloudWatch log retention for all groups at once?
Use a Lambda function triggered by a CloudWatch Events rule to enforce retention on all log groups. There are open-source solutions on GitHub (search 'cloudwatch-log-retention-lambda'). Alternatively, use AWS Config with a custom rule to detect and remediate log groups without a retention policy.
Is there a cheaper alternative to CloudWatch for application logs?
For long-term storage and querying: S3 + Athena is 10–100× cheaper than CloudWatch for bulk queries. For real-time alerting: CloudWatch Alarms remain the simplest option. For structured observability: consider OpenTelemetry with Grafana on ECS/EC2 if CloudWatch costs are significant.
What is the CloudWatch free tier?
10 custom metrics, 10 alarms, 3 dashboards, 5GB log ingestion/month, 5GB log storage, 3M API requests. After free tier: $0.50/GB ingestion, $0.03/GB storage, $0.30/metric, $0.10/alarm, $3/dashboard per month.
Should I disable CloudWatch logs for Lambda?
Only for very high-volume functions where logging adds cost without value (e.g., a function processing millions of events/day where you only care about errors). For most functions, keep logging enabled but at INFO level with a 30-day retention policy. Set LoggingConfig LoggingType: None in your Lambda configuration to fully disable.