Find unused AWS resources (and who owns them)
Published , updated
Most AWS bills include resources nobody uses any more. Each one is small, so nobody chases it; together they add up. Here's where they hide, how to find them, and how to find out whether they're safe to delete.
Where AWS waste hides
- Unattached EBS volumes. When an instance is terminated, its extra volumes often stay behind, still charged per GB-month. In the EC2 console, filter Volumes by state available.
- Old snapshots. Snapshots taken before a change, or by a backup job that was later replaced, are kept forever unless something deletes them. Sort by start time and look at anything over a few months old with no lifecycle policy.
- Idle load balancers and NAT gateways. Both charge by the hour whether or not traffic flows. A load balancer with no healthy targets, or a NAT gateway that moved a few megabytes last month, is usually left over from a project.
- Unused Elastic IPs and public IPv4 addresses. AWS charges for every public IPv4 address, attached or not.
- Stopped instances. Compute stops charging; their volumes don't. An instance stopped for months is rarely coming back.
- Databases with no connections. An RDS instance with zero connections for weeks is a test or migration that never got cleaned up.
- Logs kept forever. CloudWatch log groups default to "never expire". Set a retention period that matches what you actually need.
- Buckets without lifecycle rules. Especially versioned ones: old versions and incomplete multipart uploads pile up out of sight.
Start with AWS's own tools
- Cost Explorer shows spend by service, region and tag, which tells you where to look first.
- Trusted Advisor has cost checks that flag underused resources.
- Compute Optimizer recommends what to resize, and flags idle resources.
They show what looks unused. They don't tell you who made it, or whether it's still needed, and that's what decides whether it's safe to delete.
Check every region
The most expensive strays are often in a region nobody looks at: someone tried a tutorial in us-east-1, or a test environment was built in another region and forgotten. The console shows one region at a time, so check each enabled region, or use a tool that does.
From the command line, this lists unattached volumes in every enabled region:
for region in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
echo "$region"
aws ec2 describe-volumes --region "$region" \
--filters Name=status,Values=available \
--query 'Volumes[].[VolumeId,Size,CreateTime]' --output table
doneThe same pattern works for the others. Elastic IPs that aren't attached to anything:
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].[PublicIp,AllocationId]' --output tableLog groups that never expire:
aws logs describe-log-groups \
--query 'logGroups[?!retentionInDays].[logGroupName,storedBytes]' --output tableFind out who made it
Deleting something because it looks unused is how outages happen. Before removing anything, find its owner:
- Tags. If you tag with
Owner,CreatedByorTeam, start there. If you don't, start now: it's the cheapest fix for this whole problem. - CloudTrail. Event history keeps 90 days of management events in each region. Search for the create event (for example
CreateVolumeorCreateLoadBalancer) with the resource ID to see which user or role made it. - Infrastructure as code. If the resource is in Terraform state or a CloudFormation stack, delete it there, not by hand, or it'll come back on the next apply.
To look up a resource in CloudTrail, run this in the region it lives in:
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=ResourceName,AttributeValue=vol-0123456789abcdef0 \
--query 'Events[].[EventName,Username,EventTime]' --output tableAsk, then act
Send the owner a short list: what it is, what it costs a month, and a choice: fix it, keep it (and why), or snooze it. Record the answer. Next month you'll be glad you know that "the big volume in eu-west-1" is the finance team's archive and meant to be there.
Make it a habit
One clean-up helps; a weekly look keeps it clean. Put it on a calendar, or let a tool find new strays each week and ask their owners for you.