Free checklist · updated 2026-10-19
The 10-Point AWS Cost Checklist
The checks I run first on an AWS bill. Each one comes with the AWS CLI command that finds the waste, and what to do about it. The find commands only read; nothing changes until you run a fix.
01Delete EBS volumes nothing is attached to
A volume in the
availablestate is billed for every GB, every hour, with no instance using it. They pile up when instances are terminated without deleting their volumes.Find it
aws ec2 describe-volumes \ --filters Name=status,Values=available \ --query 'Volumes[].[VolumeId,Size,VolumeType,CreateTime]' \ --output tableFix it
Snapshot anything you are unsure about, then delete the volume. Snapshots cost less per GB than the volume itself.
02Move gp2 volumes to gp3
gp3 is cheaper per GB than gp2 and gives a baseline of 3,000 IOPS regardless of size.
Find it
aws ec2 describe-volumes \ --filters Name=volume-type,Values=gp2 \ --query 'Volumes[].[VolumeId,Size]' \ --output tableFix it
aws ec2 modify-volume --volume-id vol-0123 --volume-type gp3changes the type in place while the volume stays attached. Check the volume needs no more than gp3's baseline throughput first.Source: AWS: gp3 is up to 20% lower price per GB than gp2 (https://aws.amazon.com/ebs/general-purpose/)
03Prune old EBS snapshots
Snapshots taken for a one-off change, or by a backup job nobody reviews, stay billed until someone deletes them.
Find it
aws ec2 describe-snapshots --owner-ids self \ --query 'sort_by(Snapshots,&StartTime)[].[SnapshotId,VolumeSize,StartTime,Description]' \ --output tableFix it
Keep what your backup policy needs (and anything an AMI uses), delete the rest, and set a Data Lifecycle Manager policy so snapshots expire on their own.
04Release idle Elastic IPs and unneeded public IPv4
AWS charges for every public IPv4 address, in use or idle. An Elastic IP that is not associated with anything is pure cost.
Find it
aws ec2 describe-addresses \ --query 'Addresses[?AssociationId==null].[PublicIp,AllocationId]' \ --output tableFix it
aws ec2 release-address --allocation-id eipalloc-0123for addresses you no longer need. For private workloads, turn off auto-assigned public IPs on the subnet.Source: AWS VPC pricing: $0.005 per public IPv4 address per hour (https://aws.amazon.com/vpc/pricing/)
05Route S3 and DynamoDB traffic around the NAT Gateway
A NAT Gateway bills per hour and per GB it processes. Traffic from private subnets to S3 or DynamoDB is often the bulk of that, and gateway endpoints carry it for free.
Find it
aws ec2 describe-nat-gateways \ --query 'NatGateways[].[NatGatewayId,VpcId,State]' \ --output table # Then in Cost Explorer, group by Usage type and look for NatGateway-Bytes.Fix it
aws ec2 create-vpc-endpoint --vpc-id vpc-0123 --service-name com.amazonaws.<region>.s3 --route-table-ids rtb-0123adds an S3 gateway endpoint to the private route tables. Repeat withdynamodbif you use it.Source: AWS VPC pricing: NAT Gateway per hour and per GB; no charge for gateway endpoints (https://aws.amazon.com/vpc/pricing/)
06Set a retention period on CloudWatch log groups
New log groups default to never expire, so every log line is stored forever.
Find it
aws logs describe-log-groups \ --query 'logGroups[?!retentionInDays].[logGroupName,storedBytes]' \ --output tableFix it
aws logs put-retention-policy --log-group-name <name> --retention-in-days 30(or whatever your compliance needs say).07Give S3 buckets a lifecycle policy
Logs, exports and old build artifacts sit in S3 Standard indefinitely unless a rule moves or expires them.
Find it
for b in $(aws s3api list-buckets --query 'Buckets[].Name' --output text); do aws s3api get-bucket-lifecycle-configuration --bucket "$b" >/dev/null 2>&1 \ || echo "no lifecycle rule: $b" doneFix it
Add rules that expire temporary data and move rarely read data to a colder storage class. Also expire incomplete multipart uploads, which are billed but invisible in the console.
08Rightsize idle and oversized EC2 instances
Instances sized for a launch-day peak keep that price long after the peak is gone.
Find it
# Opt in to Compute Optimizer once, then after it has collected data: aws compute-optimizer get-ec2-instance-recommendations \ --query 'instanceRecommendations[].[instanceArn,finding,currentInstanceType]' \ --output tableFix it
Downsize instances marked over-provisioned one at a time, watching latency and memory. Where your software runs on ARM, Graviton types are usually cheaper for the same work.
Source: AWS: Graviton instances cost up to 20% less than comparable x86 instances (https://aws.amazon.com/ec2/graviton/)
09Stop non-production environments outside working hours
Dev and staging usually run all 168 hours of the week while the team uses them for about 55.
Find it
aws ec2 describe-instances \ --filters Name=instance-state-name,Values=running \ --query 'Reservations[].Instances[].[InstanceId,InstanceType,Tags[?Key==`Environment`]|[0].Value]' \ --output tableFix it
Tag non-production resources and stop them on a schedule. My open-source aws-ec2-reaper does this for EC2, RDS and ECS with Lambda and Terraform.
10Commit your steady baseline with a Savings Plan
Compute that runs around the clock is cheapest under a commitment, and AWS will tell you how much to commit based on your own usage.
Find it
aws ce get-savings-plans-purchase-recommendation \ --savings-plans-type COMPUTE_SP \ --term-in-years ONE_YEAR \ --payment-option NO_UPFRONT \ --lookback-period-in-days THIRTY_DAYSFix it
Do the cleanup above first, then commit to the steady floor of what remains, not your peak. Turn on Cost Anomaly Detection so a new spike is flagged within a day.
Source: AWS: Savings Plans save up to 72% compared to On-Demand (https://aws.amazon.com/savingsplans/)
Want a second pair of eyes on your bill?
Book a free 15-minute AWS bill review: we look at your bill together and you leave with the top 3 fixes. If you want it in writing, the AWS Cost Audit is $250 fixed, with Terraform patches for the top fixes.
Book a Free AWS Bill ReviewThe 10-point AWS cost checklist
The checks I run first on an AWS bill, each with the AWS CLI command that finds the waste and what to do about it. You can also read it on the site.