A client we'd been managing for two years asked for a routine cost review. Their CTO had already gone through the bill with finance and got nowhere — 'everything looks like it's meant to be there.' Three afternoons later, one engineer brought the monthly AWS bill from roughly $18,000 down to $12,400. No redesign. No new Savings Plan. The same workload, the same SLAs, just less waste.
Here's what we did. Three sweeps most teams already know about, and one most teams have never heard of.
Sweep #1: what's actually running versus what you've reserved
Compute reservations and Savings Plans coverage. Pulling up the utilisation report showed four Reserved RDS instances they'd migrated to Aurora Serverless v2 nine months earlier. The reservations were still being billed. That's $1,200 a month walking out the door. This is boring — but it happens at every second company we see.
Second find: EC2 Reserved Instances for old web servers that had been replaced by ECS Fargate four months ago. No alert, no dashboard. Reserved Instance Utilisation in Cost Explorer shows you these orphans in thirty seconds. You just have to look.
Sweep #2: NAT gateways nobody had audited
NAT gateways are one of the quietest line items on an AWS bill. $0.045 per hour per gateway, plus $0.045 per GB transferred. The client had six NAT gateways across four VPCs. Three served production workloads. Three served staging environments that had last been touched eight months earlier.
Those staging gateways were costing roughly $190 a month each, doing nothing. Some of the traffic going through them came from forgotten daily cron jobs nobody had switched off. We tore down the staging VPCs (with a quick ack from the client) and the gateways came down with them. −$570 a month, one afternoon of work.
Sweep #3: S3 lifecycle policies that never landed
Classic. A big logs bucket with no lifecycle rule. CloudTrail logs from 2019. ALB access logs from 2020. The client had 14 TB in S3 Standard, of which roughly 11 TB hadn't been read in over a year.
We wrote a lifecycle rule that moves logs to S3 IA after 30 days, Glacier Flexible Retrieval after 90, and Deep Archive after a year. Projected saving once it fully migrates: $850 a month. This is the cheapest saving AWS offers. You just have to write one JSON policy.
And the fourth thing, the one most teams have never heard of
Inter-AZ traffic inside a single region. AWS charges $0.01 per GB on traffic between availability zones in the same region. For most workloads it's negligible. For some, it isn't.
The client had Postgres in eu-central-1a and three ECS services in 1a, 1b and 1c. The ECS scheduler spread them across all three zones for high availability — which is the default and correct behaviour. But every database query from 1b or 1c counted as cross-AZ. At their workload that came to about 14 TB of inter-AZ traffic a month, $140.
What we did: added a Postgres read replica in 1b (the client wanted HA anyway, so this made sense) and pointed the app layer at the local replica in the same AZ for reads. Inter-AZ traffic dropped by 80%. Saving: $112 a month. A small number, but a useful illustration of where similar line items hide elsewhere.
Summary
- Sweep 1 (zombie reservations): −$1,200 a month
- Sweep 2 (staging NAT gateways): −$570 a month
- Sweep 3 (S3 lifecycle): −$850 a month (after three months)
- Sweep 4 (inter-AZ tuning): −$112 a month
- Three afternoons of work. The client was paying ~$18,000 a month before, ~$12,400 after. A 31% reduction.
Most companies don't read their AWS bill. AWS does — and it knows exactly where you've left the lights on.
There's no magic saving here. No re-architecture, no new Savings Plan, no availability trade-offs. Just people who know where to look. We run quarterly cost reviews as part of our cloud service — and when a client is paying AWS more than €5,000 a month, the first review is on us. If you'd like to see what would turn up in your bill, send us a message.