All examples for AWS Resource Cleanup Runbook

Full Account Audit

Comprehensive AWS account audit with prioritized resource checklist, copy-paste CLI commands for 10 resource types, and estimated savings potential of $155-1,040/month.

Input

What you provide to the skill

I suspect we have unused AWS resources. Can you help me audit our account and find what we can safely delete?

Output

What the skill generates for you

AWS Resource Cleanup Audit

I’ll guide you through a comprehensive audit of your AWS account. We’ll start with high-impact, low-risk resources and work our way through the priority list.

⚠️ Prerequisites Required

Before proceeding, you need:

  1. AWS CLI installed - Not currently available in this environment
  2. AWS credentials configured - Run aws configure with your access key
  3. IAM permissions - Need permissions to describe and delete resources

Priority Order

Once AWS CLI is set up, we’ll audit in this order to maximize savings while minimizing risk:

Priority Resource Monthly Cost Range Risk Time
1 Unattached EBS volumes $10-500 Low 5 min
2 Unused Elastic IPs $3.60 each Low 2 min
3 Old EBS snapshots $10-200 Low 5 min
4 Idle load balancers $20-100 each Medium 10 min
5 Stopped EC2 instances $10-500 Medium 5 min
6 Unused NAT Gateways $32.40 each Medium 5 min
7 CloudWatch Logs retention $10-100 Low 15 min
8 S3 versioning bloat $20-200 Medium 20 min
9 Old Lambda versions $5-50 Low 10 min
10 Orphaned Secrets Manager $5-20 Low 5 min

Step 1: Install AWS CLI

Choose your installation method:

macOS:

brew install awscli

Linux:

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

Windows:
Download from: https://awscli.amazonaws.com/AWSCLIV2.msi


Step 2: Configure AWS Credentials

aws configure

You’ll need:

  • AWS Access Key ID
  • AWS Secret Access Key
  • Default region (e.g., us-east-1)
  • Default output format (recommend: json)

Step 3: Start Auditing (High-Priority Resources)

🔍 Find Unattached EBS Volumes

Run this command to find volumes not attached to any instance:

aws ec2 describe-volumes \
--filters Name=status,Values=available \
--query 'Volumes[*].[VolumeId,Size,VolumeType,CreateTime,Tags[?Key==`Name`].Value|[0]]' \
--output table

What to look for: Any volumes listed are unattached and costing money.

Typical cost: $0.08/GB/month (gp3) or $0.10/GB/month (gp2)


🔍 Find Unused Elastic IPs

aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].[PublicIp,AllocationId,Tags[?Key==`Name`].Value|[0]]' \
--output table

What to look for: Unassociated IPs are costing $3.60/month each.


🔍 Find Old EBS Snapshots

aws ec2 describe-snapshots \
--owner-ids self \
--query 'Snapshots[?StartTime<=`2025-10-01`].[SnapshotId,VolumeSize,StartTime,Description]' \
--output table

What to look for: Snapshots older than 90 days with descriptions like “testing”, “temp”, or no clear purpose.

Cost: $0.05/GB/month


🔍 Find Idle Load Balancers

# Application Load Balancers
aws elbv2 describe-load-balancers \
--query 'LoadBalancers[*].[LoadBalancerName,LoadBalancerArn,CreatedTime,State.Code]' \
--output table
# Get target health (check for empty target groups)
aws elbv2 describe-target-groups \
--query 'TargetGroups[*].[TargetGroupName,TargetGroupArn]' \
--output text | while read name arn; do
count=$(aws elbv2 describe-target-health --target-group-arn $arn --query 'length(TargetHealthDescriptions)' --output text)
echo "$name: $count targets"
done

What to look for: Load balancers with zero healthy targets or no targets at all.

Cost: ~$16-20/month per Application Load Balancer + data processing fees


🔍 Find Stopped EC2 Instances

aws ec2 describe-instances \
--filters Name=instance-state-name,Values=stopped \
--query 'Reservations[*].Instances[*].[InstanceId,InstanceType,Tags[?Key==`Name`].Value|[0],StateTransitionReason]' \
--output table

What to look for: Instances stopped for more than 30 days. You still pay for EBS storage even when stopped.

Cost: EBS storage continues at $0.08-0.10/GB/month


🔍 Find Unused NAT Gateways

aws ec2 describe-nat-gateways \
--query 'NatGateways[?State==`available`].[NatGatewayId,VpcId,CreateTime,Tags[?Key==`Name`].Value|[0]]' \
--output table

What to look for: NAT Gateways in VPCs you’re no longer using or that have no private subnets routing through them.

Cost: $32.40/month + data transfer ($0.045/GB)


🔍 Find CloudWatch Logs Without Retention

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

What to look for: Log groups with null retention accumulate forever.

Cost: $0.50/GB ingested, $0.03/GB stored


🔍 Find S3 Buckets with Versioning

aws s3api list-buckets --query 'Buckets[*].Name' --output text | while read bucket; do
status=$(aws s3api get-bucket-versioning --bucket $bucket --query 'Status' --output text 2>/dev/null)
if [ "$status" = "Enabled" ]; then
echo "$bucket: Versioning ENABLED (check for old versions)"
fi
done

What to look for: Buckets with versioning enabled may have gigabytes of old versions.

Check in console: S3 > Storage Lens to see “Noncurrent version bytes”


🔍 Find Lambda Functions with Many Versions

aws lambda list-functions \
--query 'Functions[*].FunctionName' \
--output text | while read func; do
count=$(aws lambda list-versions-by-function \
--function-name $func \
--query 'length(Versions)' --output text)
if [ $count -gt 10 ]; then
echo "$func: $count versions"
fi
done

What to look for: Functions with 20+ versions. Each version consumes storage.

Cost: $0.00000003/GB-second of storage


🔍 Find Orphaned Secrets Manager Secrets

aws secretsmanager list-secrets \
--query 'SecretList[*].[Name,LastAccessedDate,CreatedDate]' \
--output table

What to look for: Secrets with no LastAccessedDate or very old access dates.

Cost: $0.40/secret/month


Next Steps

Run the audit commands above and share the results. I’ll help you:

  1. Verify safety - Check for dependencies before deletion
  2. Provide deletion commands - Step-by-step cleanup scripts
  3. Create snapshots/backups - Safety procedures for critical resources
  4. Calculate savings - Estimate monthly and annual cost reduction
  5. Set up lifecycle policies - Prevent future bloat

Safety Principles

Before deleting ANY resource:

  • Snapshot EBS volumes before deletion
  • Check tags for “production”, “backup”, “critical”
  • Verify age - Resources less than 7 days old may be in use
  • Test with one resource before batch deletion
  • Keep rollback plan - Know how to restore if needed
  • Never delete without verifying no dependencies exist

Estimated Savings Potential

Based on typical AWS account audits:

Cleanup Area Conservative Aggressive
Unattached EBS volumes $20/month $200/month
Unused Elastic IPs $10/month $40/month
Old snapshots $15/month $100/month
Idle load balancers $50/month $200/month
CloudWatch Logs retention $20/month $150/month
S3 versioning bloat $30/month $300/month
Lambda old versions $5/month $30/month
Orphaned secrets $5/month $20/month
Monthly Total $155 $1,040
Annual Total $1,860 $12,480

Most organizations find $100-500/month in easily-recoverable savings from low-risk cleanup activities.