Real scan — anonymized data
CostPatrol found $1,112/mo
in savings — 12 rules, 7 regions
We scanned a production digital platform across 7 AWS regions. NAT Gateway waste, idle Aurora clusters, excessive log retention, stale EC2 instances — CostPatrol caught it all in a single scan.
Total savings
$1,112/mo
$713 - $1,112
Findings
35
Rules matched
12
Regions scanned
7
Every finding, with exact fix commands
35 optimization opportunities across 12 rules and 7 regions. Real dollar amounts. Anonymized resource names.
NAT Gateway vs VPC Endpoints
NAT-O001 · 8 NAT gateways across 4 regions
$262 - $471/mo
ticketing-api-prod (eu-west-2)
$112 - $201/mo
4,965 GB processed · $255.86/mo · S3 and DynamoDB traffic routed through NAT
→ Create free VPC Gateway Endpoints for S3 and DynamoDB
# Create S3 Gateway Endpoint (FREE — no hourly or data charges) $ aws ec2 create-vpc-endpoint \
--vpc-id vpc-0a1b2c3d4e5f6789 \
--service-name com.amazonaws.eu-west-2.s3 \
--route-table-ids rtb-xxxxxxxxx
# Create DynamoDB Gateway Endpoint (FREE) $ aws ec2 create-vpc-endpoint \
--vpc-id vpc-0a1b2c3d4e5f6789 \
--service-name com.amazonaws.eu-west-2.dynamodb \
--route-table-ids rtb-xxxxxxxxx
payments-api-east (us-east-1)
$34 - $61/mo
1,503 GB processed · $100.04/mo · S3 and DynamoDB traffic routed through NAT
→ Create free VPC Gateway Endpoints for S3 and DynamoDB
$ aws ec2 create-vpc-endpoint \
--vpc-id vpc-1a2b3c4d5e6f7890 \
--service-name com.amazonaws.us-east-1.s3 \
--route-table-ids rtb-xxxxxxxxx
and 6 more NAT gateways across us-east-1, us-east-2, and us-west-2 — $116 - $209/mo in additional savings
RDS Cluster Sprawl
RDS-O005 · 3 Aurora PostgreSQL clusters
$202 - $288/mo
3x Aurora PostgreSQL clusters (eu-west-2)
$202 - $288/mo
3 clusters · $576.00/mo total · Each service running its own dedicated cluster
→ Consolidate 3 Aurora PostgreSQL clusters into 1 shared cluster with separate databases
# 1. Create snapshot of each cluster $ aws rds create-db-cluster-snapshot \
--db-cluster-identifier ticketing-aurora-cluster \
--db-cluster-snapshot-identifier ticketing-final-snapshot
# 2. Export and import into shared cluster $ pg_dump -h ticketing-aurora-cluster.cluster-xxxx.eu-west-2.rds.amazonaws.com \
-U admin -d ticketing_db > ticketing_backup.sql
# 3. Repeat for payments_aurora_cluster and staging_aurora_cluster # 4. Delete original clusters after verification
Idle RDS Instances
RDS-O001 · 1 resource
$72 - $144/mo
staging-aurora-node-0
$72 - $144/mo
eu-west-2 · Aurora PostgreSQL · $144.00/mo · Zero active connections
→ Stop, downsize, or delete low-utilization RDS instance
# Option 1: Snapshot and delete $ aws rds create-db-cluster-snapshot \
--db-cluster-identifier staging-aurora-cluster \
--db-cluster-snapshot-identifier staging-aurora-final
$ aws rds delete-db-instance --db-instance-identifier staging-aurora-node-0 --skip-final-snapshot
# Option 2: Downsize $ aws rds modify-db-instance --db-instance-identifier staging-aurora-node-0 --db-instance-class db.t3.micro --apply-immediately
Idle EC2 Instances
EC2-O002 · 1 resource
$69/mo
monitoring-sensor-prod
$69.12/mo
eu-west-2 · m5.large · Running but idle
→ Stop or terminate idle instance
# Option 1: Stop (can restart later) $ aws ec2 stop-instances --instance-ids i-0a1b2c3d4e5f0001
# Option 2: Terminate (permanent) $ aws ec2 terminate-instances --instance-ids i-0a1b2c3d4e5f0001
Excessive Log Retention
CWL-O001 · 5 log groups · 2.8 TB stored
$63 - $79/mo
payments-api-central
$28 - $34/mo
us-east-2 · 1,249 GB stored · 365-day retention · $37.48/mo
→ Reduce log retention to 30 days
$ aws logs put-retention-policy \
--log-group-name "payments-api-central" \
--retention-in-days 30
payments-api-east
$19 - $23/mo
us-east-1 · 848 GB stored · 365-day retention · $25.45/mo
→ Reduce log retention to 30 days
$ aws logs put-retention-policy \
--log-group-name "payments-api-east" \
--retention-in-days 30
and 3 more log groups (ticketing-api, payments-api-west, ticketing-ui) — $17 - $21/mo in additional savings
Previous-Generation Instance Types
EC2-O001 · 2 resources
$17 - $26/mo
ci-runner-build
$9 - $13/mo
eu-west-2 · t2.xlarge · $72.00/mo
→ Upgrade to t3.xlarge (Nitro-based, better price/performance)
$ aws ec2 stop-instances --instance-ids i-0b2c3d4e5f6a0002
$ aws ec2 modify-instance-attribute --instance-id i-0b2c3d4e5f6a0002 --instance-type '{"Value":"t3.xlarge"}'
$ aws ec2 start-instances --instance-ids i-0b2c3d4e5f6a0002
ci-runner-services
$9 - $13/mo
eu-west-2 · t2.xlarge · $72.00/mo
→ Upgrade to t3.xlarge (Nitro-based, better price/performance)
$ aws ec2 modify-instance-attribute --instance-id i-0c3d4e5f6a7b0003 --instance-type '{"Value":"t3.xlarge"}'
GP2 to GP3 EBS Migration
EBS-O001 · 5 volumes
$12/mo
vol-0a1b2c3d4e5f0001
$4.00/mo
gp2 · 200GB · attached to ci-runner-build
→ Migrate to GP3 (20% cheaper, 3000 IOPS + 125 MB/s baseline included)
$ aws ec2 modify-volume --volume-id vol-0a1b2c3d4e5f0001 --volume-type gp3
and 4 more GP2 volumes (200GB, 100GB, 80GB, 9GB) — $7.78/mo in additional savings
S3 Missing Lifecycle Rules
S3-O001 · 1 resource
$7 - $11/mo
platform-access-logs
$6.55 - $11.45/mo
711 GB · $16.36/mo · No lifecycle policy
→ Add lifecycle policy to transition to Intelligent-Tiering after 30 days
$ aws s3api put-bucket-lifecycle-configuration \
--bucket platform-access-logs \
--lifecycle-configuration '{
"Rules": [{
"ID": "TransitionToIntelligentTiering",
"Status": "Enabled",
"Filter": {},
"Transitions": [{ "Days": 30, "StorageClass": "INTELLIGENT_TIERING" }]
}]
}'
Orphaned Elastic IPs
EIP-O001 · 1 resource
$3.60/mo
monitoring-sensor
$3.60/mo
eu-west-2 · Elastic IP not associated with any resource
→ Release orphaned Elastic IP address
$ aws ec2 release-address --allocation-id eipalloc-0a1b2c3d4e5f
Unnecessary Public IPv4 Addresses
OPT-018 · 1 resource
$3.60/mo
monitoring-sensor-prod
$3.60/mo
eu-west-2 · Instance has public IPv4 but only needs private networking
→ Remove unnecessary public IPv4 and use private networking
$ aws ec2 modify-subnet-attribute \
--subnet-id subnet-0a1b2c3d4e5f \
--no-map-public-ip-on-launch
Lambda Memory Right-Sizing
LAM-O002 · 5 resources
$2 - $3/mo
search-indexer-prod
$0.80 - $1.00/mo
eu-west-2 · 2048MB allocated · 192MB peak usage · $1.14/mo
→ Reduce memory from 2048MB to 256MB (90% over-provisioned)
$ aws lambda update-function-configuration \
--function-name search-indexer-prod \
--memory-size 256
and 4 more over-provisioned Lambda functions — $1.51 - $1.89/mo in additional savings
Lambda ARM64 Migration
LAM-O001 · 4 resources
$1/mo
search-indexer-prod
$0.17 - $0.29/mo
eu-west-2 · x86_64 · nodejs20.x · 2048MB · $1.14/mo
→ Migrate to ARM64 (Graviton2) for 20% cost savings
$ aws lambda update-function-configuration \
--function-name search-indexer-prod \
--architectures arm64
and 3 more x86_64 Lambda functions eligible for ARM64 migration
What AWS Cost Explorer misses
AWS Cost Explorer
Shows $526/mo in NAT Gateway charges — no traffic breakdown
Cannot tell you which traffic could use free VPC endpoints
Doesn't flag 2.8 TB of logs with excessive retention
Misses idle EC2, orphaned EIPs, and previous-gen instances
CostPatrol
"Create free S3/DynamoDB Gateway Endpoints — save $471/mo instantly"
12 different rule types — network, compute, storage, database, serverless
7 regions scanned simultaneously in a single run
Copy-paste AWS CLI commands for every finding
AWS tells you NAT Gateway costs went up. CostPatrol tells you that S3 and DynamoDB traffic is flowing through $526/mo in NAT Gateways — when free VPC Gateway Endpoints would handle it for $0.
More real AWS scan reports
See what CostPatrol finds in your AWS account
Free scan shows your total savings. Upgrade to Pro for full findings, fix commands, and daily Slack alerts.