Skip to main content
All articles

Cloud Log Management at Scale: Costs, Retention, and Avoiding the $10K/Month Surprise

CloudWatch Logs, Azure Monitor, and GCP Cloud Logging pricing traps, log routing, sampling, retention policies, and cost reduction strategies with real numbers.

CloudToolStack TeamFebruary 17, 202614 min read

The $10K/Month Logging Bill Nobody Planned For

Every cloud logging pricing page makes it look cheap. CloudWatch Logs charges $0.50 per GB ingested. Azure Monitor Logs charges a few dollars per GB. GCP Cloud Logging is free for the first 50GB per month. These numbers seem reasonable until you realize how much log data a production environment actually generates.

A medium-sized Kubernetes cluster with 100 pods, each logging at a modest 10 lines per second, generates roughly 300GB of log data per month. An API Gateway handling 50 million requests per month with full access logging adds another 100GB. Application-level structured logging with request/response bodies can easily generate 500GB to 1TB per month for a service handling moderate traffic.

At CloudWatch Logs pricing, 1TB of ingestion is $500 per month -- and that is just ingestion. Storage is another $0.03 per GB per month. Log Insights queries are $0.005 per GB scanned. If your developers are running 20 queries per day across 1TB of logs, that is another $900 per month in query charges alone. Suddenly your logging bill is $1,500 per month for a single service. Scale that across 20 services and you are looking at the $10,000-per-month surprise bill that gives this article its title.

I have helped teams reduce logging costs by 60 to 80 percent without losing any diagnostic capability. The techniques are not secret or complex -- they just require thinking about logging as an engineering problem rather than a checkbox you enable and forget about.

Where the Money Actually Goes

AWS CloudWatch Logs

CloudWatch Logs has three cost components: ingestion ($0.50/GB), storage ($0.03/GB/month), and querying via Log Insights ($0.005/GB scanned). The ingestion cost is usually the largest component, but storage sneaks up on you because most teams set retention to "never expire" by default. A team ingesting 500GB per month with no retention policy will accumulate 6TB in a year, costing $180 per month in storage alone.

The less obvious cost trap is cross-region log replication. If you are using CloudWatch cross-account or cross-region log subscription filters to centralize logs, you pay ingestion costs in both the source and destination accounts. A common architecture -- application logs in us-east-1 replicated to a central logging account -- doubles your ingestion cost.

Log Insights query costs are per GB scanned, and there is no query caching. Running the same query twice scans the data twice and charges you twice. In organizations where multiple engineers troubleshoot the same issue, I have seen Log Insights charges exceed ingestion costs during incident response.

CloudWatch Logs Query Starter

Azure Monitor Logs (Log Analytics)

Azure Monitor Logs uses a workspace-based pricing model with two tiers: pay-as-you-go ($2.76 per GB for the first 5GB/day, then commitment tiers) and commitment tiers that offer 15 to 30 percent discounts for guaranteed daily volume. The pricing is straightforward but significantly more expensive per GB than CloudWatch for high-volume ingestion.

The hidden cost in Azure is the data retention beyond the default 30 days. Extended retention is $0.10 per GB per month for interactive retention (queryable) and $0.02 per GB per month for archive tier (requires restore before querying). The archive tier seems cheap until you need to query it -- restoring archived data takes minutes to hours and costs $0.13 per GB restored.

Azure also charges for certain data types that you might not expect. Basic Logs tables (which replaced the deprecated Basic tier) ingest at a lower rate but charge $0.005 per GB for queries, similar to CloudWatch Log Insights. The Analytics tables provide full query capability but cost more to ingest. Choosing the right table type for each log category is one of the biggest Azure logging cost levers.

Azure Monitor Query Builder

GCP Cloud Logging

GCP's pricing is deceptively simple: the first 50GB per project per month is free, and everything above that is $0.50 per GB. But GCP also has a unique cost trap: logs that are routed to Cloud Logging (the default sink) count toward the ingestion volume even if you exclude them from storage. The exclusion filter prevents storage costs but not ingestion costs.

The way to avoid ingestion charges for unwanted logs in GCP is to configure exclusion filters at the log router level before the logs reach Cloud Logging. This is a subtle but critical distinction -- a storage exclusion filter saves on storage but still charges for ingestion, while a router-level exclusion prevents both ingestion and storage charges.

GCP's Log Analytics, which provides BigQuery-compatible SQL querying over log data, requires upgrading your log bucket to use Log Analytics. Once upgraded, you get powerful SQL queries, but you also start paying BigQuery query processing fees on top of logging ingestion and storage costs. For teams that query logs heavily, this can add 20 to 40 percent to the total logging bill.

GCP Cloud Logging Query Builder

Default retention is your enemy

Across all three clouds, the most common logging cost mistake is accepting the default retention policy. CloudWatch Logs default to "never expire." Azure defaults to 30 days (reasonable) but many teams extend it to 90 or 365 days without calculating the cost. GCP defaults to 30 days with a maximum of 3,650 days. Set explicit retention policies for every log group on day one. Application logs rarely need more than 30 days of hot retention. Archive to cheap storage (S3, Azure Blob, GCS) for compliance requirements that mandate longer retention.

Cost Reduction Strategy 1: Log Routing and Filtering

The most impactful cost reduction technique is preventing unnecessary logs from reaching your logging service in the first place. In every production environment I have audited, 40 to 60 percent of log volume comes from three categories: health check logs, verbose framework debug output, and duplicate information logged at multiple levels of the stack.

Health Check Logs

Load balancers and Kubernetes liveness/readiness probes generate a health check request every 10 to 30 seconds per target. For a service with 20 pods behind an ALB, that is 40 to 120 health check requests per second. If your application logs each request, health checks alone generate 3.5 to 10 million log entries per day -- potentially hundreds of gigabytes per month of completely useless data.

The fix is straightforward: filter health check requests at the application level (do not log requests to /health or /ready endpoints), at the load balancer level (ALB access logs can exclude health check traffic), and at the log router level (CloudWatch subscription filters, Azure diagnostic settings, GCP log router exclusions).

Verbose Framework Logging

Most web frameworks and ORMs log at INFO level by default, which includes every database query, every HTTP client request, and every middleware execution. In production, this detail is almost never needed and can account for 30 to 50 percent of log volume. Set your production log level to WARN for framework and library loggers, keeping INFO only for your application code. This single change typically reduces log volume by 30 to 40 percent.

Duplicate Logging

A request to a Kubernetes-hosted API might be logged by: the load balancer access log, the ingress controller, the service mesh sidecar, the application framework, and the application code. That is five log entries for a single request, and they often contain overlapping information. Identify which layer provides the most useful data for your troubleshooting workflow and disable logging at the redundant layers. In most cases, application-level structured logging plus load balancer access logs covers all diagnostic and compliance needs.

Cost Reduction Strategy 2: Structured Logging and Sampling

Structured logging (JSON format with consistent fields) is not just a best practice for searchability -- it directly reduces costs by enabling efficient filtering, compression, and sampling.

Log Sampling

For high-volume, low-signal log streams -- access logs for a service handling millions of requests per day, for example -- logging every request is wasteful. A 10 percent sample of access logs provides the same statistical visibility into error rates, latency distributions, and traffic patterns as 100 percent logging, at one-tenth the cost.

Implement sampling at the application level using a deterministic sampling strategy (sample based on a hash of the request ID so that you always get the complete lifecycle of sampled requests). Most structured logging libraries support sampling natively. In Kubernetes, you can also configure Fluentd or Fluent Bit to sample log entries before forwarding them to your logging backend.

The key insight is that not all log streams need the same sampling rate. Error logs should never be sampled -- you want 100 percent of errors. Successful request logs can be sampled at 1 to 10 percent. Debug-level logs in production should either be disabled entirely or sampled at 0.1 percent, enabled only for specific request paths when debugging an issue.

Dynamic sampling

The most sophisticated approach is dynamic sampling, where the sampling rate adjusts based on the log content. Services like Honeycomb popularized this pattern. The idea: sample frequent, expected events (successful requests, cache hits) at a low rate and keep 100 percent of rare, interesting events (errors, high-latency requests, unusual status codes). You can implement this in your application code or in a log processing pipeline. The result is a dramatically smaller log volume that retains all the diagnostic value.

Cost Reduction Strategy 3: Tiered Storage

Not all logs need to be in a hot, queryable state. A tiered storage strategy routes logs to different backends based on their age and access patterns.

Hot tier (0 to 7 days): Keep recent logs in your primary logging service (CloudWatch, Azure Monitor, Cloud Logging) for real-time querying and alerting. This is the expensive tier, so minimize volume with the filtering and sampling techniques above.

Warm tier (7 to 30 days): Move logs to cheaper queryable storage. On AWS, this means exporting to S3 and querying with Athena ($5 per TB scanned, no ingestion cost). On Azure, use Basic Logs tables or archive tier with restore on demand. On GCP, route to BigQuery or a Cloud Storage bucket with BigQuery external table access.

Cold tier (30+ days): Archive to the cheapest available storage for compliance. S3 Glacier Deep Archive ($0.00099/GB/month), Azure Archive Blob ($0.00099/GB/month), or GCS Archive ($0.0012/GB/month). These are for compliance retention only -- you should not need to query these under normal circumstances.

The math is compelling. For 1TB of monthly log volume with a 90-day compliance requirement: keeping everything in CloudWatch for 90 days costs roughly $500 ingestion + $90 storage + queries = $600+ per month. Using tiered storage with 7 days hot, 30 days warm (S3 + Athena), and 90 days cold (Glacier) costs roughly $500 ingestion + $3 hot storage + $15 warm storage + $3 cold storage + $5 occasional Athena queries = $526 per month. The savings grow dramatically with longer retention requirements.

Cost Reduction Strategy 4: Alternative Backends

Cloud-native logging services are convenient but expensive. For teams with significant log volumes (1TB+ per month), self-managed or third-party logging backends can reduce costs by 50 to 80 percent.

OpenSearch / Elasticsearch

Running OpenSearch on reserved instances in your own VPC gives you full-text search, dashboards, and alerting at a fraction of the cost of CloudWatch Log Insights or Azure Log Analytics for high-volume use cases. AWS OpenSearch Serverless starts at around $700 per month minimum, but a managed OpenSearch cluster with reserved instances can handle 1TB per day of ingestion for $1,500 to $3,000 per month, depending on retention and query patterns. Compare that to $15,000 per month for CloudWatch at the same volume.

Grafana Loki

Loki is the most cost-effective log aggregation system I have used. Unlike Elasticsearch, Loki does not index log content -- it indexes labels (metadata) and stores log data as compressed chunks in object storage. This means ingestion is fast and cheap, storage costs are essentially the cost of S3 or GCS, and queries that filter by labels first are extremely efficient.

The tradeoff is query performance. Full-text searches across unindexed content are slow compared to Elasticsearch. But for the most common log query pattern -- "show me logs for service X, environment production, in the last hour, containing the word error" -- Loki performs well because the label filters (service, environment, time range) narrow the search space before the content filter applies.

Running Loki on Kubernetes with S3 or GCS as the storage backend handles 1TB per day of log ingestion for roughly $200 to $500 per month in compute and storage costs. That is an order of magnitude cheaper than any cloud-native logging service.

A Real Cost Reduction Case Study

Here are the actual numbers from a cost reduction project I led for a team running 40 microservices on EKS with approximately 300 pods:

Before optimization: 2.1TB per month CloudWatch ingestion ($1,050), 6.3TB stored with no retention policy ($189), Log Insights queries ($450). Total: $1,689 per month.

Optimizations applied:

  1. Filtered health check and readiness probe logs at the application level. Reduced volume by 22 percent.
  2. Set framework loggers (Spring Boot, Hibernate) to WARN in production. Reduced volume by an additional 28 percent.
  3. Implemented 10 percent sampling for successful request access logs. Reduced volume by an additional 18 percent.
  4. Set 14-day retention on all log groups. Eliminated $189 in storage overage.
  5. Exported 14-day to 90-day logs to S3 with Athena for ad-hoc querying.

After optimization: 672GB per month CloudWatch ingestion ($336), 672GB stored for 14 days ($6), Log Insights queries ($150, less data to scan), S3 storage ($15), Athena queries ($10). Total: $517 per month. A 69 percent reduction with no loss of diagnostic capability.

Start with visibility

Before optimizing, you need to know where your log volume comes from. On AWS, use CloudWatch Metrics to see ingestion volume per log group. On Azure, check the Usage table in Log Analytics. On GCP, use the Cloud Logging metrics explorer to see bytes ingested per log name. In every case I have seen, 80 percent of the volume comes from fewer than 20 percent of the log sources. Focus your optimization effort there.

Implementation Checklist

  1. Audit current volume and costs. Pull the last three months of logging costs broken down by log group or source. Identify the top 10 contributors by volume.
  2. Set retention policies. Every log group should have an explicit retention period. 7 to 14 days hot retention covers most troubleshooting needs. 30 to 90 days in warm storage covers most compliance requirements.
  3. Filter health checks and probes. This is the easiest win and typically reduces volume by 15 to 25 percent.
  4. Tune log levels. Production should log at WARN for frameworks and INFO for application code. Implement dynamic log level changes via feature flags for debugging.
  5. Implement sampling. Start with 10 percent sampling on your highest-volume, lowest-signal log streams. Validate that metrics and alerting still work correctly.
  6. Set up tiered storage. Route logs older than your hot retention period to object storage with query-on-demand capability.
  7. Evaluate alternative backends. If your monthly log volume exceeds 1TB, run a cost comparison between your current cloud-native service and Loki or OpenSearch.
  8. Monitor continuously. Set up alerts for logging cost spikes. A new service deployment that accidentally enables debug logging can undo all your optimization work in a single day.

Related Tools

Written by CloudToolStack Team

Cloud architects with 15+ years of production experience across AWS, Azure, GCP, and OCI. We build free tools and write practical guides to help engineers navigate multi-cloud infrastructure.

Disclaimer: This article is for informational purposes. Cloud services and pricing change frequently; always verify with official provider documentation. AWS, Azure, GCP, and OCI are trademarks of their respective owners.