Most AWS bills don't explode. They creep. A test server nobody turned off, a disk left behind after an instance was deleted, logs that are kept forever. None of them is dramatic on its own, which is exactly why they survive for years.
After more than 25 years in tech, I keep finding the same culprits. Here is the list I check first, with the quickest way to spot each one.
1. Servers that are running but barely working
An EC2 instance is billed every hour it runs, whether it serves a thousand requests or none.
How to spot it: in CloudWatch, look at CPUUtilization for the last 14 days. An instance that averages under 10% and never goes above 40% can usually drop one size, which roughly halves its price. One that never passes 5% may not be needed at all.
Watch out: CPU isn't everything. Check memory too (it needs the CloudWatch agent) before downsizing.
2. Disks with no server attached
When you terminate an instance, its EBS volumes are not always deleted. They keep costing money every month.
How to spot it: EC2 → Volumes → filter by State = available. Snapshot anything you're unsure about, then delete the volume.
3. Old gp2 volumes
gp3 volumes cost about 20% less per GB than gp2 and give you a baseline of 3,000 IOPS regardless of size. Most workloads can switch in place, with no downtime.
How to spot it: EC2 → Volumes → look at the Volume type column.
4. Snapshots from years ago
Snapshots are incremental, so a single old one is cheap. Hundreds of them are not. Neither are the AMIs nobody remembers creating.
How to spot it: EC2 → Snapshots → Owned by me, sort by date. Then set a retention rule with Data Lifecycle Manager or AWS Backup so it doesn't happen again.
5. Public IP addresses you are not using
Since 2024, AWS charges for every public IPv4 address, about $3.60 per month each, whether it's in use or not.
How to spot it: EC2 → Elastic IPs. Any address with no association can be released.
6. NAT Gateway traffic that didn't need to go through it
A NAT Gateway charges per hour and per GB processed. A classic surprise is private servers downloading from S3 or DynamoDB through the NAT.
How to spot it: in Cost Explorer, group by Usage type and look for NatGateway-Bytes. Adding a gateway VPC endpoint for S3 and DynamoDB is free and takes that traffic off the NAT.
7. Load balancers with nothing behind them
A load balancer has a fixed hourly price even with zero traffic. Old campaign sites and abandoned test environments leave these behind.
How to spot it: EC2 → Load Balancers → check each target group for registered targets.
8. Logs that are kept forever
The default retention for CloudWatch Logs is never expire. Verbose application logs can grow quietly for years.
How to spot it: CloudWatch → Log groups → the Retention column. Set 30 or 90 days for most groups, and export to S3 anything you must keep longer.
9. S3 data that nobody reads
Backups, logs and old uploads sit in S3 Standard by default, the most expensive storage class.
How to spot it: S3 → bucket → Metrics for size, and Management for lifecycle rules. Move rarely-read data to Intelligent-Tiering or a Glacier class with a lifecycle rule.
10. Paying on-demand for usage that never changes
If you run roughly the same amount of compute every month, you are leaving money on the table. A 1-year Compute Savings Plan with no upfront payment typically saves around 20–30% on EC2, Fargate and Lambda.
How to spot it: Billing → Savings Plans → Recommendations. Clean up items 1 to 9 first, then commit to about 70% of your lowest monthly compute spend to keep the risk low.
11. Dev and test environments running 24/7
A development environment used during business hours is idle about 70% of the week. Scheduling it to stop at night and on weekends cuts its compute cost by roughly that much.
How to spot it: look for instances and databases with dev, test or staging in their names. AWS Instance Scheduler or a simple EventBridge rule can stop and start them.
Bonus: two risks that cost more than any bill
While you are in there, check two things that have nothing to do with cost but everything to do with sleeping well:
- MFA on the root account. Without it, a single leaked password can cost you the whole account.
- Automated backups on every production database. RDS → database → Backup retention period should never be 0.
Automating the checks
Doing this by hand once is a good exercise. Doing it every quarter is tedious, so I packaged my checklist as an open-source, read-only toolkit:
- a CloudFormation template that creates a view-only role (it explicitly blocks reading files, secrets and database items);
- a collector that refuses any API call that isn't a read, and anonymizes the output;
- an analyzer that turns the data into a prioritized PDF report with estimated savings and fix steps.
GitHub: https://github.com/pizzettiandre/aws-cost-review-kit
Rather have someone do it for you?
If you'd prefer an architect to run the review, interpret the numbers and hand you a clear plan, I offer it here:
https://www.fiverr.com/alpizzetti/review-your-aws-architecture-and-cut-your-aws-bill
Access is read-only and nothing is ever changed in your account.
All prices mentioned are approximate us-east-1 list prices at the time of writing. Check the AWS Pricing Calculator for your region.

