Available now for new projects.Get a free DevOps audit →

Blog / Cloud Cost

Why Is My AWS Bill So High? 12 Common Reasons (and How to Fix Each)

A bill that doubled overnight is rarely one big mistake. It is usually five or six small charges you cannot see on the summary page. Here are the 12 that show up on almost every account I audit, and the exact fix for each, so you can find yours in the next 30 minutes.

First, find where the money actually goes

Do not guess. Open Cost Explorer, set the view to the last month, and group by Usage Type (not just by service). That one setting turns a vague “EC2 is expensive” into “$430 of it is NAT Gateway data processing.” From the CLI:

aws ce get-cost-and-usage \
  --time-period Start=2026-07-01,End=2026-07-29 \
  --granularity MONTHLY --metrics UnblendedCost \
  --group-by Type=DIMENSION,Key=USAGE_TYPE
Where the ~40% savings come fromUsersglobal trafficCloudFrontcache, less egressALBload balancerAuto Scalingright-sized EC2RDSright-sized DBS3 + lifecyclecold data → cheaper tierSavings Planssteady workloadsCloudWatchbudget alertsScale to zerooff-peak, nightlyCyan = the levers that cut the bill without hurting performance.
The cyan blocks are the usual suspects: compute, storage, network and databases.

The network charges nobody sees (1 to 3)

These are the silent killers. They almost never appear in the console UI you look at daily.

  • 1. NAT Gateway processing. You pay per hour and roughly $0.045 for every GB that passes through. Route S3 and DynamoDB traffic through free VPC gateway endpoints instead, and it disappears.
  • 2. Cross-AZ data transfer. Traffic between Availability Zones is billed both ways. Chatty services split across AZs quietly rack up charges. Keep tightly-coupled components in the same AZ.
  • 3. Internet egress. Data out to the internet runs about $0.09/GB. Put CloudFront in front of it: cheaper per GB, and faster for users.
# Terraform: a free S3 gateway endpoint removes NAT charges for S3
resource "aws_vpc_endpoint" "s3" {
  vpc_id            = aws_vpc.main.id
  service_name      = "com.amazonaws.us-east-1.s3"
  vpc_endpoint_type = "Gateway"
  route_table_ids   = [aws_route_table.private.id]
}

Compute you are paying full price for (4 to 6)

  • 4. On-demand for steady workloads. Baseline compute that runs 24/7 should be on a 1-year Savings Plan (up to ~66% off). Keep on-demand only for spiky traffic.
  • 5. Oversized instances. Pull 2 to 4 weeks of CloudWatch metrics and size to your p95, not the peak. Most fleets run at 10 to 20% utilization.
  • 6. Old-generation instances. Moving from m5 to Graviton (m7g) is often ~20% cheaper for more performance. It is usually a one-line change.

Storage that piles up quietly (7 to 9)

  • 7. Idle and orphaned resources. Unattached EBS volumes, old snapshots, idle load balancers, and unused Elastic IPs (which are now billed) cost money for nothing. Delete them.
  • 8. Everything in S3 Standard. Add lifecycle rules so logs and backups roll to Infrequent Access, then Glacier. Also delete incomplete multipart uploads, they are invisible but billed.
  • 9. gp2 volumes. Switch EBS from gp2 to gp3: about 20% cheaper with higher baseline performance.

Databases and logs (10 to 12)

  • 10. Over-provisioned RDS. Right-size the instance, stop non-production databases outside work hours, question Multi-AZ on dev, and prune old automated and manual snapshots.
  • 11. CloudWatch Logs with no retention. Log groups default to never expire. Ingestion plus storage compounds for months. Set a retention policy (30 to 90 days) on every group.
  • 12. No tags, no budgets. If nobody owns the bill, drift never gets caught. Add cost allocation tags by team and environment, and an AWS Budgets alert so a spike never lands silently again.

The 30-minute triage

  • Cost Explorer, grouped by Usage Type, to see the real breakdown.
  • Kill idle resources: unattached EBS, old snapshots, spare Elastic IPs.
  • Check NAT Gateway and cross-AZ transfer first, they hide the most.
  • Set CloudWatch Logs retention and S3 lifecycle rules.
  • Cover your steady baseline with a Savings Plan, then set a budget alert.

Once the emergency is handled, the proactive version of this lives in my AWS cost optimization guide, the checklist I run to keep the bill flat as you grow.

Not sure which of the 12 is yours?

I'll run a free 30-minute audit on your AWS account and send back a prioritized report of exactly where your money is leaking, no obligation.

Get a free DevOps audit →