Strays

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

Start with AWS's own tools

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
done

The 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 table

Log groups that never expire:

aws logs describe-log-groups \
  --query 'logGroups[?!retentionInDays].[logGroupName,storedBytes]' --output table

Find out who made it

Deleting something because it looks unused is how outages happen. Before removing anything, find its owner:

  1. Tags. If you tag with Owner, CreatedBy or Team, start there. If you don't, start now: it's the cheapest fix for this whole problem.
  2. CloudTrail. Event history keeps 90 days of management events in each region. Search for the create event (for example CreateVolume or CreateLoadBalancer) with the resource ID to see which user or role made it.
  3. 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 table

Ask, 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.