Skip to content
Anit Rai
Go back

AWS cost audit in 40 min: the exact CLI commands

Here’s the exact workflow I use. No third-party tools, no dashboards — just the AWS CLI and some jq.

Find old RDS snapshots

# Snapshots older than 90 days, sorted by size
aws rds describe-db-snapshots \
  --snapshot-type manual \
  --query 'DBSnapshots[?SnapshotCreateTime<=`2025-12-24`].[DBSnapshotIdentifier,SnapshotCreateTime,AllocatedStorage]' \
  --output table

Anything in that list that isn’t explicitly retained for compliance is waste.

Find unattached Elastic IPs

aws ec2 describe-addresses \
  --query 'Addresses[?AssociationId==null].[PublicIp,AllocationId]' \
  --output table

Release them:

# For each AllocationId in the output above:
aws ec2 release-address --allocation-id eipalloc-XXXXXXXX

Find orphaned EBS volumes

aws ec2 describe-volumes \
  --filters Name=status,Values=available \
  --query 'Volumes[*].[VolumeId,Size,CreateTime]' \
  --output table

“Available” means unattached. If it’s been available for more than a week, it’s probably orphaned.

Find NAT Gateway data transfer spend

aws ce get-cost-and-usage \
  --time-period Start=2026-02-01,End=2026-03-01 \
  --granularity MONTHLY \
  --filter '{"Dimensions":{"Key":"USAGE_TYPE","Values":["NatGateway-Bytes"]}}' \
  --metrics "UnblendedCost"

If this is non-trivial, add VPC endpoints for S3 and DynamoDB immediately:

# Get your VPC and route table IDs first
VPC_ID=$(aws ec2 describe-vpcs --query 'Vpcs[?IsDefault==`false`].VpcId' --output text | head -1)
RT_ID=$(aws ec2 describe-route-tables --filters "Name=vpc-id,Values=$VPC_ID" --query 'RouteTables[0].RouteTableId' --output text)

# Create S3 endpoint (free)
aws ec2 create-vpc-endpoint \
  --vpc-id $VPC_ID \
  --service-name com.amazonaws.ap-south-1.s3 \
  --route-table-ids $RT_ID

# Create DynamoDB endpoint (free)
aws ec2 create-vpc-endpoint \
  --vpc-id $VPC_ID \
  --service-name com.amazonaws.ap-south-1.dynamodb \
  --route-table-ids $RT_ID

EC2 snapshots older than 90 days

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

The full audit takes me about 40 minutes on a new account. I usually find $500–$3k in monthly waste on accounts spending $10k+/month.

See the CXO version for the business framing.


Share this post on:

Previous Post
Your AWS bill has a $2k leak. Here's what it looks like.
Next Post
Storing data in the wrong country is now a compliance violation. Here's how we built for that.