Every AWS account I've audited has real, findable waste in the same handful of places. Nothing exotic. Boring, structural waste that piles up because nobody seems to notice it.
Here's the checklist I actually use, roughly in order of dollar impact.
1. Compute
- Idle or oversized EC2 instances. CloudWatch CPU/memory utilization under 10-15% sustained for two-plus weeks is your signal. AWS Compute Optimizer (free, opt-in) will do this analysis for you if you haven't turned it on yet.
- Stopped-but-not-terminated instances. A stopped instance still bills for any attached EBS volume. "Stopped" is not "free."
- Graviton migration. M6g/C6g instances typically run 10-20% cheaper than M5/C5 for compatible workloads, same performance.
- Dev/test running 24/7. Scheduling non-prod off nights and weekends is roughly a 65% runtime reduction for zero functional cost.
2. Storage
- Unattached EBS volumes.
State = availablevolumes billed with nothing attached to them, extremely common after instance termination when "delete on termination" wasn't set. - gp2 to gp3. About 20% cheaper at the same baseline performance. Same-day, zero-downtime conversion. There's rarely a reason not to do this immediately.
- S3 storage-class mismatches. Data sitting in Standard that's rarely accessed should be in Standard-IA, Glacier, or Glacier Deep Archive.
- Missing lifecycle policies. Buckets with no lifecycle rule at all: logs, backups, uploads that should be auto-transitioning or expiring and aren't.
3. Networking
- NAT Gateway cost. Bills per-hour and per-GB processed. Check whether VPC Endpoints (S3/DynamoDB Gateway endpoints are free) can take some of that traffic off it.
- Unused Elastic IPs. Billed hourly whether they're attached to anything or not.
- Idle load balancers. ALBs/NLBs with no healthy targets or near-zero traffic.
4. Database
- Oversized RDS instances. Same CPU/memory review as EC2.
- Idle non-prod databases running 24/7.
- Multi-AZ on non-prod. Doubles cost, so confirm it's only turned on where it's actually needed.
5. Commitment discounts
- RI/Savings Plan coverage at 0% on steady-state workloads means you're paying full on-demand rate for predictable usage. Check Cost Explorer's coverage report.
- Utilization matters too, not just coverage. Commitments you've already bought but aren't fully using are wasted money in the other direction.
6. Serverless
- Over-provisioned Lambda memory. Cost scales with memory times duration.
- Unused provisioned concurrency. Bills whether it's invoked or not.
7. Logging
- CloudWatch Log Groups set to "Never Expire." That's the default. Nobody changes it. It quietly racks up cost forever until someone notices.
8. Governance
- Missing cost-allocation tags. If you can't attribute spend to a team, you can't hold anyone accountable for it.
- No budget alarms. Overspend gets discovered at month-end instead of in real time.
Every one of these is checkable by hand. If you'd rather not click through Cost Explorer and the EC2/S3/CloudWatch consoles yourself, I built a script that automates the API-checkable parts of this list: unattached volumes, unused EIPs, RI coverage, S3 lifecycle gaps, log retention. It's part of the AWS Cost Audit Kit on Gumroad. I've run it against multiple real AWS accounts before shipping it, and the first account run found 11 buckets with no lifecycle policy and 29 log groups set to never expire.
But the checklist above is the actually useful part, and it's free right here. Use it however you want.
Top comments (0)