Most AWS bills grow quietly. A test environment is left running, a few snapshots pile up every night, a NAT gateway carries more traffic than anyone expected. None of it is dramatic, but together it often adds up to a large share of the monthly invoice.
This is the checklist our engineers work through when a client asks us to look at their AWS spend. Start at the top: the first few items usually take an afternoon and pay back the fastest.
Before you start: open AWS Cost Explorer and group last month’s spend by service, then by linked account. Knowing which three services make up most of the bill tells you where to focus.
Quick wins: clean up what nobody is using
1. Delete unattached EBS volumes
When an EC2 instance is terminated, its data volumes are not always deleted with it. These unattached volumes keep billing every month. In the EC2 console, filter volumes by the state available; anything there is not attached to an instance. Snapshot it first if you are unsure, then delete it.
2. Expire old snapshots
Nightly snapshots with no retention rule grow forever. Use Amazon Data Lifecycle Manager or AWS Backup to keep, for example, 14 daily and 6 monthly copies, and remove the rest. Check for snapshots of volumes that no longer exist; they are often the largest forgotten cost.
3. Release idle public IP addresses and load balancers
AWS charges for every public IPv4 address, including Elastic IPs that are not attached to anything. Idle load balancers also carry a fixed hourly charge even with no traffic. Review both in each region you use, not only your main one.
4. Switch gp2 volumes to gp3
gp3 volumes cost less per GB than gp2 and let you set IOPS and throughput separately from size. For most workloads the change can be made on a live volume with no downtime. It is one of the safest savings available.
Rightsizing: pay for what you use
5. Rightsize EC2 and RDS with Compute Optimizer
AWS Compute Optimizer analyses CPU, memory (with the CloudWatch agent) and network use and recommends smaller or different instance types. Instances that run at 5 to 10 percent CPU most of the day are common candidates. Change one environment at a time and watch performance for a week.
6. Consider Graviton instances
AWS Graviton (Arm-based) instances generally offer better price-performance than comparable x86 instances. Managed services such as RDS, ElastiCache and many container workloads can often move with little or no code change. Test first: some older software is only built for x86.
7. Schedule non-production environments
Development and test environments rarely need to run at night or at weekends. Stopping them outside working hours with the AWS Instance Scheduler, or a simple scheduled Lambda function, removes most of their compute cost. A typical working week is about a third of the hours in a full week.
Commitments: the biggest discounts
8. Cover steady workloads with Savings Plans
Once usage is rightsized, commit to the baseline with Savings Plans or Reserved Instances. Compute Savings Plans apply across EC2, Fargate and Lambda and across instance families and regions, so they are the flexible default. Commit to the usage you are confident will still be there in a year, not your peak.
| Option | Best for | Flexibility |
|---|---|---|
| Compute Savings Plans | Most steady compute | Any instance family, region, EC2, Fargate or Lambda |
| EC2 Instance Savings Plans | Stable fleets on one instance family | Size and OS can change within the family and region |
| Reserved Instances (RDS, ElastiCache and others) | Databases and caches | Tied to engine and region |
| Spot Instances | Batch jobs, CI runners, stateless workers | Can be interrupted at short notice |
9. Use Spot for interruptible work
Build servers, data processing and stateless workers that can restart safely are good fits for Spot capacity, which is sold at a steep discount to on-demand prices. Combine several instance types in an Auto Scaling group so a single capacity shortage does not stop the work.
Hidden costs most teams miss
10. Watch NAT gateway and data transfer charges
NAT gateways charge for every GB they process. If private instances pull large amounts of data from S3 or DynamoDB through a NAT gateway, add gateway VPC endpoints for those services; gateway endpoints for S3 and DynamoDB have no hourly charge. Also check cross-AZ traffic between chatty services, which is billed in both directions.
11. Put S3 data in the right storage class
Logs, backups and old uploads rarely need S3 Standard. Lifecycle rules can move objects to Infrequent Access or Glacier classes after a set number of days and delete them when they are no longer needed. For data with unpredictable access, S3 Intelligent-Tiering moves objects automatically.
Keep it from creeping back
12. Tag everything, set budgets and turn on anomaly detection
Savings fade if nobody owns the bill. Agree a small set of tags such as environment, owner and project, activate them as cost allocation tags, and set AWS Budgets alerts per team. AWS Cost Anomaly Detection will email you when spend on a service jumps unexpectedly, often days before the invoice would have shown it.
Where to start
- This week: items 1 to 4. Low risk, and they pay back immediately.
- This month: items 5 to 7 and 10 to 11, one environment at a time.
- After a month of stable usage: commit with item 8.
- Ongoing: item 12, reviewed monthly.
Cost work is not a one-off project. New services get launched, teams grow and usage shifts. A short monthly review of the top services and any anomalies keeps the savings in place.
Want us to run this checklist on your account?
We review your AWS spend, show you where the waste is and estimate the savings before you commit to anything.
Book a free 30-minute call