Cutting CloudWatch Logs Costs: Ingestion Is the Bill, Not Storage
When a CloudWatch bill grows, the culprit is almost always Logs, and within Logs, ingestion. The conclusion up front: ingestion at about $0.50/GB costs 17 times as much as storage (about $0.03 per GB-month), so savings come from reducing what flows in, not from deleting old logs. However aggressively you trim retention, the $0.50 per GB already ingested never comes back. Log-level discipline, the Infrequent Access class, and alternate destinations are what actually move the bill. The full checklist for a bill that jumped is in the 10 most common causes. Prices are for us-east-1.
The pricing structure #
| Item | Rate | Notes |
|---|---|---|
| Ingestion (Standard) | ~$0.50/GB | 5GB/month free, volume tiers (from $0.25 past 10TB) |
| Ingestion (Infrequent Access) | ~$0.25/GB | Half of Standard, real-time features restricted |
| Storage | ~$0.03/GB-month | Compressed size |
| Logs Insights queries | ~$0.005 per GB scanned | Proportional to scan range |
| S3 export and subscription delivery | Separate delivery fees | Bulk archive belongs in S3 |
Why ingestion is the bill #
Price a service ingesting 10GB a day and the structure is obvious: 300GB a month at about $150 to ingest, while even three months of accumulation stores for about $27 a month. Cutting retention from a year to a month saves a few dollars; trimming ingestion 30% through log levels saves $45 every month. The target is the inflow, not the pile.
Retention still needs setting, though. Log groups default to never-expire, so neglected groups grow storage costs quietly and forever. Applying retention account-wide (30–90 days for production, whatever compliance dictates for audit logs) belongs on the standing checklist. For long-term retention requirements, export to S3 and let its archive classes hold the history at a fraction of the price.
High-volume organizations get tiered rates: Standard ingestion is $0.50/GB up to 10TB a month, $0.25 for the next 20TB, then $0.10 and $0.05 further up. At tens of TB a month the effective rate falls below half without negotiating anything, flattening the bill’s slope.
Infrequent Access and intelligent tiering #
Switching a log group to the Infrequent Access (IA) class halves ingestion to $0.25/GB. The price is real-time capability: IA groups cannot use Live Tail, metric filters, subscription filters, or alarm wiring, while Logs Insights queries still work. The dividing line: logs that feed alarms stay Standard; logs you only search when something breaks go IA. Debug logs, access logs, and batch-job logs are the typical candidates.
July 2026 added intelligent tiering, which classifies log data automatically across Standard, Infrequent Access, and Archive Instant Access based on access patterns. At a scale where assigning classes per log group by hand is impractical, this does the sorting for you. As a new feature, confirm the requirements (eligible log groups, tiering conditions) in the docs before relying on it.
Lambda has one extra option. Since 2025, Lambda logs get tiered ingestion pricing and can be routed directly to S3 or Data Firehose instead of CloudWatch. High-volume function logs sent straight into an analytics pipeline (S3 plus Athena, for instance) never pass through CloudWatch ingestion at all. Start with functions whose logs nobody reads in CloudWatch anyway.
Reducing what you ingest #
- Log levels: DEBUG left on in production is the biggest waste pattern. Running INFO normally and lowering the level only during investigations often cuts tens of percent by itself.
- Structure and dedupe: JSON logging puts one event on one line; duplicate stack traces and full request-body logging are the bulk patterns to remove.
- Sampling: high-traffic paths that need no per-request logging (health checks, static assets) get excluded or sampled. Infrastructure logs like ALB access logs and VPC Flow Logs can also be scoped to needed fields and targets.
- Insights habits: query costs scale with GB scanned, so narrow time ranges and specific log groups keep investigation costs down.
Order of attack #
- Find out which log groups ingest how much: Cost Explorer plus the per-group IncomingBytes metric ranks the sources. A few groups usually account for most of it.
- Set retention everywhere: remove never-expire. Storage is not the big number, but unattended it only grows. Long-term needs go to S3.
- Clean up levels, duplicates, and sampling on the top ingesters: shrinking inflow is the largest lever the pricing structure offers.
- Move non-real-time logs to IA: confirm nothing depends on alarms or metric filters, then take the half rate. At scale, let intelligent tiering do the classification.
- Reroute heavy Lambda logs: functions with no reason to keep logs in CloudWatch go straight to S3 or Firehose, bypassing ingestion pricing entirely.
Summary #
- The substance of CloudWatch Logs cost is ingestion (~$0.50/GB), 17 times storage (~$0.03 per GB-month). Savings come from cutting inflow.
- Never-expire is the default retention, which is its own trap. Set retention on every log group and archive long-term history in S3.
- The IA class halves ingestion. Alarm-feeding logs stay Standard, search-only logs go IA, and the 2026 intelligent tiering automates the sorting at scale.
- Lambda logs can bypass CloudWatch entirely via S3 and Firehose destinations. Review the highest-volume functions first.
- Always-on DEBUG, duplicated stack traces, and full health-check logging are the three big waste patterns. Remove them from the top ingesters first.