August 19, 20268 min read

Why your AWS bill keeps growing even when traffic doesn’t

Many AWS costs are decoupled from request volume — they accrue on provisioned capacity, stored bytes, and background data movement, not on how many users hit your app. Here are the specific line items that climb while traffic stays flat, and where to look first.

Every quarter someone opens Cost Explorer, sees the total up again, and asks the obvious question: traffic is flat, so why is the bill climbing? The instinct is to look for a spike in requests. There usually isn’t one. The bill grew because many AWS costs are only loosely coupled to how many users hit your application — it’s tied to what you’ve provisioned, what you’re storing, and what your infrastructure moves in the background.

That’s the premise worth internalizing: an AWS bill is largely a function of accumulated inventory and provisioned capacity, not this month’s traffic. Once you see which line items bill on time, bytes, or allocation rather than on requests, a rising bill under flat load stops being a mystery and becomes a list of specific, findable things.

Provisioned capacity bills on time, not requests

On many bills, a large share of cost is provisioned capacity that charges by the hour whether or not anything uses it — though the exact proportion depends on your workload mix. An EC2 instance bills for every hour it’s running, idle or saturated. An EBS volume bills for its provisioned size, not the bytes you’ve written — a 500 GB gp3 volume that’s 5% full still bills for 500 GB. Provisioned IOPS and throughput bill the same way.

The clearest example is one AWS added recently: since February 1, 2024, every public IPv4 address costs $0.005 per hour — about $3.60 a month — whether it’s attached to a busy instance or sitting on a forgotten Elastic IP. A fleet with a few hundred public IPs is paying four figures a month for addressing alone, and not one dollar of it responds to traffic.

Autoscaling doesn’t save you here either. A group with a minimum capacity of six instances runs six instances at 3 a.m. with zero requests. The floor is a fixed cost you chose; scaling only adds on top of it.

Storage only accretes

Storage is the quietest driver because it’s designed to grow and never shrink on its own. S3 does not delete an object for you — without a lifecycle policy, a bucket’s size only increases, and you pay per GB-month for the running total. Old build artifacts, exported reports, and log dumps sit there billing indefinitely.

Snapshots compound the same way. EBS snapshots are incremental — each stores only the blocks that changed — but every snapshot you retain adds to a total that keeps growing until something expires it. An automated daily-snapshot policy with no retention limit is a line item that rises every single day, entirely independent of load.

The network bills you for moving bytes, not serving users

Data transfer is where “flat external traffic” is most misleading, because many of the bytes AWS charges for never reach a user. Traffic between availability zones is billed per GB in each direction, and the exact rate depends on region and architecture — so a service mesh spread across AZs pays a recurring toll on its own internal chatter. Inter-region replication and data-out to the internet add more.

NAT Gateway deserves its own mention because it bills two ways at once: roughly $0.045 per hour for the gateway itself in us-east-1 — about $32 a month before a single byte moves — plus ~$0.045 per GB processed (both rates vary by region). Private subnets pulling container images, OS packages, or S3 data through a NAT Gateway rack up processing charges that track deployment and background jobs, not user requests.

Observability scales with your fleet, not your traffic

CloudWatch Logs is billed on the volume you ingest and how long you retain it, not on request count — so the charge tracks how many services emit logs and how verbose they are. In the Standard log class that ingestion runs on the order of $0.50 per GB in us-east-1 (a cheaper Infrequent Access class exists, and rates vary by region), plus a per-GB-month storage charge for retention. Leave debug logging on across a growing fleet and ingestion climbs while traffic sits still. Custom metrics, high-resolution metrics, and X-Ray traces add their own per-unit charges that scale with instrumentation, not usage.

This is a common shape: the team adds services and dashboards over two quarters, log volume doubles, and the observability line on the bill doubles with it — with no change in application traffic at all.

Managed services keep the meter running

Provisioned managed databases and caches bill on instance-hours and allocated storage, not on query count. A provisioned RDS, ElastiCache, or OpenSearch cluster costs the same whether it serves a million queries an hour or zero — the instance runs and bills regardless. (Serverless and on-demand modes exist precisely to tie cost to usage, but a provisioned cluster is a fixed hourly charge.) A staging cluster nobody has queried in weeks, a read replica added “just in case,” an oversized db.r6g chosen for a load test that never got downsized — each bills continuously and none of it reacts to traffic.

Why the number ratchets up month over month

Put those together and the trend explains itself. Cloud inventory is easy to create and rarely removed: resources get spun up for a project, the project ends, and the resources keep billing. Snapshots and logs accumulate by policy. S3 grows because nothing deletes it. Orphaned volumes, unattached Elastic IPs, and idle endpoints sit on the bill precisely because nothing is watching them. The total rises not because you’re busier but because the pile is bigger than last month’s.

Where to look first, in rough order of how often it’s the answer:

  • Idle and oversized compute — instances and managed clusters running at consistently low utilization, and instance types picked for a peak that never recurs.
  • Unattached and over-provisioned storage — orphaned EBS volumes, volumes far larger than their used size, and buckets with no lifecycle policy.
  • Snapshot and log retention — automated snapshots and log groups with no expiry, growing every day.
  • Network plumbing — NAT Gateway data processing and cross-AZ transfer that scale with architecture, not users.
  • Forgotten addressing — public IPv4 addresses and Elastic IPs on stopped or unused resources.

Why is my AWS bill higher this month if nothing changed?

Because “nothing changed” usually refers to traffic, and traffic isn’t what most of the bill measures. Between two flat-traffic months, storage grew (S3 has no automatic deletion, snapshots accumulated, logs kept ingesting), and any resource added earlier is now billing for a full month instead of a partial one. Compare the two months in Cost Explorer grouped by service and by usage type — the delta typically traces to storage, data transfer, or a resource that was created and left running, rather than to request-driven cost.

Does reducing traffic lower my AWS bill?

Only for the usage-metered parts of your bill. Cutting requests reduces things billed per unit of work — data-out, NAT Gateway data processing, Lambda invocations, per-request managed-service charges. It does nothing for provisioned capacity, storage, snapshots, IPv4 addressing, or a managed cluster’s instance-hours, all of which bill regardless of load. To move those you have to change the inventory — rightsize, delete, set retention — not the traffic.

Which AWS costs are fixed regardless of usage?

Anything billed on provisioning, uptime, or stored bytes rather than requests: running EC2 and managed-database instance-hours, provisioned EBS size and IOPS, S3 and snapshot storage, the NAT Gateway hourly charge, and public IPv4 addresses. These form a floor your bill won’t drop below no matter how quiet the application gets — which is exactly why a bill can rise on flat traffic, and why optimization work targets the inventory, not the load. (List prices above are us-east-1 examples and shift over time; confirm current rates on the AWS pricing pages.)

Connect a read-only IAM role and CloudQuell’s savings engine flags the non-traffic drivers by name — idle EC2, idle NAT Gateways, unattached volumes and orphaned snapshots, idle public IPv4 — each with a monthly-dollar estimate, and its anomaly detection alerts you when a service’s spend starts climbing. Free under $10K/month.

Try CloudQuell
← Back to all posts