For small engineering teams, managing AWS spending is often secondary to shipping features. However, resource leakage—such as orphaned database backups, oversized virtual servers, and unused IP addresses—can quietly inflate your bill.
In this guide, we'll cover an actionable cost optimization checklist designed to reduce your monthly AWS spend by 20% to 40% without impacting application reliability.
Immediate Win: Many teams can save hundreds of dollars in under an hour simply by cleaning up detached storage volumes and unused public IP allocations.
The Checklist at a Glance
- Clean up Orphaned Resources: Detached EBS volumes, unused Elastic IPs (EIPs), and old snapshots.
- Right-Size Compute Instances: Downsizing oversized EC2, ECS, or RDS instances.
- Automate Dev Environment Schedules: Turning off staging and testing nodes outside working hours.
- Optimize Storage: Applying S3 lifecycle rules to archive log files.
- Upgrade to Modern Families: Moving workloads to Graviton (ARM) instances.
1. Cleaning up Orphaned Storage (EBS)
When you terminate an EC2 instance, its attached Elastic Block Store (EBS) volume is often preserved on disk. These "detached" volumes continue to accumulate storage fees.
Run this AWS CLI command to list all detached EBS volumes currently incurring charges in your default region:
dinesh@devops ~ ❯ aws ec2 describe-volumes --filters Name=status,Values=available --query "Volumes[*].{ID:VolumeId,Size:Size}" --output table ----------------------- | DescribeVolumes | +---------------------+ | ID | Size | +--------------+------+ | vol-08a... | 100 | | vol-0cf... | 50 | +--------------+------+
Delete these volumes using aws ec2 delete-volume --volume-id <id> to stop the charges immediately.
2. Stop Paying for Idle Public IPs
AWS charges for Elastic IP addresses that are allocated to your account but not attached to a running EC2 instance. Identify and release these unused resources:
dinesh@devops ~ ❯ aws ec2 describe-addresses --query "Addresses[?InstanceId==null].{IP:PublicIp,AllocationId:AllocationId}" --output table
3. Automate Nightly Shutdowns
Development and staging environments are typically only needed during working hours (roughly 50 hours a week). Leaving them running 24/7 (168 hours a week) wastes nearly 70% of their operational costs.
Implement a lightweight cron script or utilize **AWS Instance Scheduler** to turn off non-essential nodes at 7:00 PM and restart them at 8:00 AM on weekdays.
4. S3 Lifecycle Storage Policies
If you write application logs or database backups to Amazon S3, they accumulate over time, increasing your storage costs. Configure an S3 Lifecycle Rule to transition older objects to colder storage or delete them automatically.
This rule transitions objects in the /logs path to **S3 Glacier Flexible Retrieval** after 30 days, and deletes them after 90 days:
{
"Rules": [
{
"ID": "MoveLogsToGlacier",
"Status": "Enabled",
"Filter": { "Prefix": "logs/" },
"Transitions": [
{ "Days": 30, "StorageClass": "GLACIER" }
],
"Expiration": { "Days": 90 }
}
]
}
5. Upgrade to Graviton (ARM)
When launching new EC2 or RDS instances, choose the Graviton processor family (e.g. t4g, c7g, m7g) over standard x86 instances. Graviton instances deliver up to **40% better price-performance** and cost 20% less per hour.
Conclusion
Cost optimization is an ongoing practice. By automating the cleanup of detached storage volumes, releasing idle public IPs, shutting down development hosts overnight, and utilizing storage lifecycle tiers, small teams can significantly reduce their AWS spending and focus their budget on scaling their core application.