StackSage — Cloud Cost Audit Report

Account: 123456789012 | Regions: us-east-1, us-west-2 | Generated: 2026-02-03 08:32:06 UTC | Pricing: v2025-12

Executive Dashboard

$302.9
Potential Savings/Month
24
Issues Found
9
High Priority Items
67%
Potential Waste

Estimated Monthly Cost: $448.75

Data Sources:
📊 Live Metrics (CloudWatch, 7d) 💰 Cost Explorer Data CW Queries: 15/12/3

Historical Spend (2025-11-01 → 2025-12-01): $1240.55

💰 Historical Spend Breakdown (Top)

Top Services
Service Cost (USD)
Amazon EC2 $530.17
Amazon RDS $260.34
AWS NAT Gateway $95.0
Amazon S3 $93.32
Amazon CloudWatch $44.9
Top Regions
Region Cost (USD)
us-east-1 $895.58
us-west-2 $128.15

Executive Summary

Potential monthly savings: $302.90. Current cost (flagged resources): $448.75. Primary drivers: underutilized_rds(prod-postgres-db): $78.00, idle_ec2(i-0123456789abcdef0): $62.40, unattached_ebs(vol-fedcba9876543210): $50.00, old_snapshot(snap-old123456789abc): $25.00, idle_elb(my-alb-prod): $25.00

🛡️ Security Posture Scorecard

A quick view of baseline security controls (pass/fail/unknown). See Security Posture Findings for details.

Control Status
Root MFA + no root keys FAIL
Password policy baseline FAIL
Access key hygiene PASS
S3 account public access block FAIL
S3 default encryption PASS
EBS encryption by default PASS
CloudTrail baseline FAIL
AWS Config recorder PASS
GuardDuty enabled FAIL
Security Hub enabled PASS
CloudWatch alarms present PASS

🎯 Top Savings Opportunities

Resource Distribution

📋 Implementation Roadmap

🔥 Critical Priority (3)

  • enable-root-mfa
  • remove-root-access-keys
  • consider-stopping-or-rightsize
    💰 Save $62.4/month

⚡ High Priority (6)

  • enable-cloudtrail
  • enable-s3-block-public-access
  • restrict-security-group-ingress
  • snapshot-and-delete
    💰 Save $10.0/month
  • snapshot-and-delete
    💰 Save $50.0/month

💡 Top 5 Quick Wins

Type Resource Region Est. Savings (USD/mo) Recommended Action
underutilized_rds prod-postgres-db us-east-1 $78.0 review-and-rightsize
idle_ec2 i-0123456789abcdef0 us-east-1 $62.4 consider-stopping-or-rightsize
unattached_ebs vol-fedcba9876543210 us-west-2 $50.0 snapshot-and-delete
old_snapshot snap-old123456789abc us-west-2 $25.0 delete-snapshot
idle_elb my-alb-prod us-east-1 $25.0 review-and-delete-if-unused
Resource Type Count
account 6
security-group 1
ec2 1
ebs 4
snapshot 2
cloudwatch 1
lambda 1
eip 2
nat 1
elb 3
rds 2
Type Resource Region Severity Est. Cost (USD/mo) Est. Savings (USD/mo) Recommended Action Estimation
underutilized_rds 75% Skipped prod-postgres-db
db.t3.large → db.t3.medium
us-east-1 MEDIUM 156.0 78.0 review-and-rightsize
Metric query skipped due to budget exhaustion
Heuristic
idle_ec2 95% Measured i-0123456789abcdef0 us-east-1 CRITICAL 62.4 62.4 consider-stopping-or-rightsize
Low CPU and low network usage over the lookback window.
Heuristic
unattached_ebs 50% vol-fedcba9876543210 us-west-2 HIGH 50.0 50.0 snapshot-and-delete
EBS volume (500 GB) unattached for >7 days. Create snapshot for safety, then delete if unused.
Heuristic
idle_elb 90% Measured my-alb-prod us-east-1 HIGH 25.0 25.0 review-and-delete-if-unused
Low request count over the lookback window.
Verify (AWS CLI)
aws cloudwatch get-metric-statistics --namespace AWS/ApplicationELB --metric-name RequestCount --dimensions Name=LoadBalancer,Value=app/my-alb-prod/1234567890abcdef --start-time $(date -u -v-7d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 86400 --statistics Sum
Heuristic
old_snapshot 50% snap-old123456789abc
964 days old
us-west-2 MEDIUM 25.0 25.0 delete-snapshot
Snapshot is older than the retention window.
Verify (AWS CLI)
aws ec2 describe-snapshots --snapshot-ids snap-old123456789abc
Heuristic
lb_empty_target_groups 90% old-api-alb us-west-2 MEDIUM 22.5 22.5 delete-if-unused
APPLICATION load balancer with 2 target group(s), all empty (0 registered targets). Likely leftover from decommissioned application.
Verify (AWS CLI)
# Check load balancer details aws elbv2 describe-load-balancers --names old-api-alb --region us-west-2 # List all target groups aws elbv2 describe-target-groups --load-balancer-arn arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/old-api-alb/abc123 --region us-west-2 # Check target health for each group (example for first group) aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/api-backend-tg/xyz789 --region us-west-2 aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/api-frontend-tg/xyz790 --region us-west-2
Heuristic
unattached_ebs 50% vol-0123456789abcdef us-east-1 HIGH 10.0 10.0 snapshot-and-delete
EBS volume (100 GB) unattached for >7 days. Create snapshot for safety, then delete if unused.
Heuristic
cloudwatch_logs_retention 50% /aws/lambda/data-processor us-east-1 MEDIUM 15.0 9.0 set-logs-retention
Log group retention is set to Never Expire; set retention to reduce storage costs.
Verify (AWS CLI)
aws logs describe-log-groups --log-group-name-prefix /aws/lambda/data-processor --query 'logGroups[0].retentionInDays'
Heuristic
gp2_to_gp3_migration 50% vol-1111222233334444 us-east-1 MEDIUM 25.0 5.0 migrate-to-gp3
gp3 is typically cheaper than gp2 for similar workloads.
Verify (AWS CLI)
aws ec2 describe-volumes --volume-ids vol-1111222233334444 --query 'Volumes[0].VolumeType' aws ec2 describe-volumes-modifications --volume-id vol-1111222233334444
Heuristic
old_snapshot 50% snap-0123456789abcdef
668 days old
us-east-1 LOW 5.0 5.0 delete-snapshot
Snapshot is older than the retention window.
Heuristic
unused_eip 50% 54.123.45.67 us-east-1 MEDIUM 4.0 4.0 release-eip
Elastic IP is not attached to any instance; AWS charges for unused EIPs.
Verify (AWS CLI)
aws ec2 describe-addresses --public-ips 54.123.45.67
Heuristic
unused_eip 50% 34.210.98.76 us-west-2 MEDIUM 4.0 4.0 release-eip
Elastic IP is not attached to any instance; AWS charges for unused EIPs.
Verify (AWS CLI)
aws ec2 describe-addresses --public-ips 34.210.98.76
Heuristic
overprovisioned_lambda 50% data-transformer us-east-1 LOW 12.0 3.0 reduce-lambda-memory
Execution time indicates memory may be over-provisioned. Estimated using measured invocations (~36,000/mo).
Verify (AWS CLI)
aws lambda get-function-configuration --function-name data-transformer --query 'MemorySize' aws cloudwatch get-metric-statistics --namespace AWS/Lambda --metric-name Duration --dimensions Name=FunctionName,Value=data-transformer --start-time $(date -u -v-7d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 3600 --statistics Average
Heuristic
ebs_overprovisioned_performance 50% vol-5555666677778888 us-east-1 MEDIUM None None reduce-provisioned-performance
Provisioned performance appears high for observed usage over 14 days. Avg IOPS 120 (prov 9000), avg throughput 5.2 MB/s (prov 250 MB/s).
Verify (AWS CLI)
aws ec2 describe-volumes --volume-ids vol-5555666677778888 aws cloudwatch get-metric-statistics --namespace AWS/EBS --metric-name VolumeReadOps --dimensions Name=VolumeId,Value=vol-5555666677778888 --start-time $(date -u -v-14d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 300 --statistics Sum aws cloudwatch get-metric-statistics --namespace AWS/EBS --metric-name VolumeWriteOps --dimensions Name=VolumeId,Value=vol-5555666677778888 --start-time $(date -u -v-14d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 300 --statistics Sum aws cloudwatch get-metric-statistics --namespace AWS/EBS --metric-name VolumeReadBytes --dimensions Name=VolumeId,Value=vol-5555666677778888 --start-time $(date -u -v-14d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 300 --statistics Sum aws cloudwatch get-metric-statistics --namespace AWS/EBS --metric-name VolumeWriteBytes --dimensions Name=VolumeId,Value=vol-5555666677778888 --start-time $(date -u -v-14d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 300 --statistics Sum
Heuristic
idle_elb 35% No Data CloudWatch returned no datapoints for the lookback window. my-alb-staging us-west-2 LOW 0.0 0.0 review-lb-usage
Unable to measure load balancer request volume: CloudWatch returned no datapoints for the lookback window.
Verify (AWS CLI)
aws cloudwatch get-metric-statistics --namespace AWS/ApplicationELB --metric-name RequestCount --dimensions Name=LoadBalancer,Value=app/my-alb-staging/abcdef1234567890 --start-time $(date -u -v-7d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 86400 --statistics Sum
Heuristic
nat_gateway 70% nat-0123456789abcdef us-east-1 LOW 32.85 0.0 review-and-consider-vpc-endpoint
NAT gateways have hourly + data processing cost; if used primarily for S3, consider an S3 VPC endpoint.
Verify (AWS CLI)
aws ec2 describe-nat-gateways --nat-gateway-ids nat-0123456789abcdef aws ec2 describe-route-tables --filters Name=route.nat-gateway-id,Values=nat-0123456789abcdef
📐 Estimation Method: base_hourly+uptime • Adjusted cost: $32.85/mo • Assumptions: ['no data processing included', 'uptime estimated from CreateTime', 'regional multiplier applied via pricing tables']
underutilized_rds 30% Access Denied Missing CloudWatch permissions to read metrics for this resource. analytics-postgres-db
db.t3.large
us-east-1 LOW 0.0 0.0 review-and-rightsize
Unable to measure CPU/storage utilization: missing CloudWatch permissions (AccessDenied).
Heuristic
Type Resource Region Severity Est. Cost (USD/mo) Est. Savings (USD/mo) Recommended Action Estimation
iam_root_access_keys_present 100% root None CRITICAL None 0 remove-root-access-keys
Root access keys are present. Delete root access keys and use least-privilege IAM roles/users.
Heuristic
iam_root_mfa_disabled 100% root None CRITICAL None 0 enable-root-mfa
Root MFA is not enabled. Enable MFA on the root user and restrict root usage.
Heuristic
cloudtrail_not_configured 90% account None HIGH None 0 enable-cloudtrail
CloudTrail baseline appears incomplete. Enable an org/account trail (multi-region) and ensure it is actively logging.
Heuristic
s3_account_public_access_block_disabled 90% account None HIGH None 0 enable-s3-block-public-access
S3 account-level Block Public Access is not fully enabled.
Heuristic
sg_open_to_world 95% sg-0123abcd4567efgh8 us-east-1 HIGH None 0 restrict-security-group-ingress
Security group allows inbound access from the public internet on sensitive ports.
Heuristic
guardduty_not_enabled 80% account None MEDIUM None 0 enable-guardduty
GuardDuty is not enabled in one or more regions checked.
Heuristic
iam_password_policy_weak 95% account None MEDIUM None 0 harden-iam-password-policy
IAM password policy is weaker than common baseline settings.
Heuristic
Type Resource Region Severity Est. Cost (USD/mo) Est. Savings (USD/mo) Recommended Action Estimation
iam_root_mfa_disabled 100% root None CRITICAL None 0 enable-root-mfa
Root MFA is not enabled. Enable MFA on the root user and restrict root usage.
Heuristic
iam_root_access_keys_present 100% root None CRITICAL None 0 remove-root-access-keys
Root access keys are present. Delete root access keys and use least-privilege IAM roles/users.
Heuristic
iam_password_policy_weak 95% account None MEDIUM None 0 harden-iam-password-policy
IAM password policy is weaker than common baseline settings.
Heuristic
cloudtrail_not_configured 90% account None HIGH None 0 enable-cloudtrail
CloudTrail baseline appears incomplete. Enable an org/account trail (multi-region) and ensure it is actively logging.
Heuristic
s3_account_public_access_block_disabled 90% account None HIGH None 0 enable-s3-block-public-access
S3 account-level Block Public Access is not fully enabled.
Heuristic
sg_open_to_world 95% sg-0123abcd4567efgh8 us-east-1 HIGH None 0 restrict-security-group-ingress
Security group allows inbound access from the public internet on sensitive ports.
Heuristic
guardduty_not_enabled 80% account None MEDIUM None 0 enable-guardduty
GuardDuty is not enabled in one or more regions checked.
Heuristic
idle_ec2 95% Measured i-0123456789abcdef0 us-east-1 CRITICAL 62.4 62.4 consider-stopping-or-rightsize
Low CPU and low network usage over the lookback window.
Heuristic
unattached_ebs 50% vol-0123456789abcdef us-east-1 HIGH 10.0 10.0 snapshot-and-delete
EBS volume (100 GB) unattached for >7 days. Create snapshot for safety, then delete if unused.
Heuristic
unattached_ebs 50% vol-fedcba9876543210 us-west-2 HIGH 50.0 50.0 snapshot-and-delete
EBS volume (500 GB) unattached for >7 days. Create snapshot for safety, then delete if unused.
Heuristic
gp2_to_gp3_migration 50% vol-1111222233334444 us-east-1 MEDIUM 25.0 5.0 migrate-to-gp3
gp3 is typically cheaper than gp2 for similar workloads.
Verify (AWS CLI)
aws ec2 describe-volumes --volume-ids vol-1111222233334444 --query 'Volumes[0].VolumeType' aws ec2 describe-volumes-modifications --volume-id vol-1111222233334444
Heuristic
ebs_overprovisioned_performance 50% vol-5555666677778888 us-east-1 MEDIUM None None reduce-provisioned-performance
Provisioned performance appears high for observed usage over 14 days. Avg IOPS 120 (prov 9000), avg throughput 5.2 MB/s (prov 250 MB/s).
Verify (AWS CLI)
aws ec2 describe-volumes --volume-ids vol-5555666677778888 aws cloudwatch get-metric-statistics --namespace AWS/EBS --metric-name VolumeReadOps --dimensions Name=VolumeId,Value=vol-5555666677778888 --start-time $(date -u -v-14d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 300 --statistics Sum aws cloudwatch get-metric-statistics --namespace AWS/EBS --metric-name VolumeWriteOps --dimensions Name=VolumeId,Value=vol-5555666677778888 --start-time $(date -u -v-14d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 300 --statistics Sum aws cloudwatch get-metric-statistics --namespace AWS/EBS --metric-name VolumeReadBytes --dimensions Name=VolumeId,Value=vol-5555666677778888 --start-time $(date -u -v-14d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 300 --statistics Sum aws cloudwatch get-metric-statistics --namespace AWS/EBS --metric-name VolumeWriteBytes --dimensions Name=VolumeId,Value=vol-5555666677778888 --start-time $(date -u -v-14d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 300 --statistics Sum
Heuristic
old_snapshot 50% snap-old123456789abc
964 days old
us-west-2 MEDIUM 25.0 25.0 delete-snapshot
Snapshot is older than the retention window.
Verify (AWS CLI)
aws ec2 describe-snapshots --snapshot-ids snap-old123456789abc
Heuristic
cloudwatch_logs_retention 50% /aws/lambda/data-processor us-east-1 MEDIUM 15.0 9.0 set-logs-retention
Log group retention is set to Never Expire; set retention to reduce storage costs.
Verify (AWS CLI)
aws logs describe-log-groups --log-group-name-prefix /aws/lambda/data-processor --query 'logGroups[0].retentionInDays'
Heuristic
overprovisioned_lambda 50% data-transformer us-east-1 LOW 12.0 3.0 reduce-lambda-memory
Execution time indicates memory may be over-provisioned. Estimated using measured invocations (~36,000/mo).
Verify (AWS CLI)
aws lambda get-function-configuration --function-name data-transformer --query 'MemorySize' aws cloudwatch get-metric-statistics --namespace AWS/Lambda --metric-name Duration --dimensions Name=FunctionName,Value=data-transformer --start-time $(date -u -v-7d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 3600 --statistics Average
Heuristic
unused_eip 50% 54.123.45.67 us-east-1 MEDIUM 4.0 4.0 release-eip
Elastic IP is not attached to any instance; AWS charges for unused EIPs.
Verify (AWS CLI)
aws ec2 describe-addresses --public-ips 54.123.45.67
Heuristic
unused_eip 50% 34.210.98.76 us-west-2 MEDIUM 4.0 4.0 release-eip
Elastic IP is not attached to any instance; AWS charges for unused EIPs.
Verify (AWS CLI)
aws ec2 describe-addresses --public-ips 34.210.98.76
Heuristic
nat_gateway 70% nat-0123456789abcdef us-east-1 LOW 32.85 0.0 review-and-consider-vpc-endpoint
NAT gateways have hourly + data processing cost; if used primarily for S3, consider an S3 VPC endpoint.
Verify (AWS CLI)
aws ec2 describe-nat-gateways --nat-gateway-ids nat-0123456789abcdef aws ec2 describe-route-tables --filters Name=route.nat-gateway-id,Values=nat-0123456789abcdef
📐 Estimation Method: base_hourly+uptime • Adjusted cost: $32.85/mo • Assumptions: ['no data processing included', 'uptime estimated from CreateTime', 'regional multiplier applied via pricing tables']
lb_empty_target_groups 90% old-api-alb us-west-2 MEDIUM 22.5 22.5 delete-if-unused
APPLICATION load balancer with 2 target group(s), all empty (0 registered targets). Likely leftover from decommissioned application.
Verify (AWS CLI)
# Check load balancer details aws elbv2 describe-load-balancers --names old-api-alb --region us-west-2 # List all target groups aws elbv2 describe-target-groups --load-balancer-arn arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/old-api-alb/abc123 --region us-west-2 # Check target health for each group (example for first group) aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/api-backend-tg/xyz789 --region us-west-2 aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:us-west-2:123456789012:targetgroup/api-frontend-tg/xyz790 --region us-west-2
Heuristic
idle_elb 90% Measured my-alb-prod us-east-1 HIGH 25.0 25.0 review-and-delete-if-unused
Low request count over the lookback window.
Verify (AWS CLI)
aws cloudwatch get-metric-statistics --namespace AWS/ApplicationELB --metric-name RequestCount --dimensions Name=LoadBalancer,Value=app/my-alb-prod/1234567890abcdef --start-time $(date -u -v-7d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 86400 --statistics Sum
Heuristic
idle_elb 35% No Data CloudWatch returned no datapoints for the lookback window. my-alb-staging us-west-2 LOW 0.0 0.0 review-lb-usage
Unable to measure load balancer request volume: CloudWatch returned no datapoints for the lookback window.
Verify (AWS CLI)
aws cloudwatch get-metric-statistics --namespace AWS/ApplicationELB --metric-name RequestCount --dimensions Name=LoadBalancer,Value=app/my-alb-staging/abcdef1234567890 --start-time $(date -u -v-7d '+%Y-%m-%dT%H:%M:%S') --end-time $(date -u '+%Y-%m-%dT%H:%M:%S') --period 86400 --statistics Sum
Heuristic
underutilized_rds 75% Skipped prod-postgres-db
db.t3.large → db.t3.medium
us-east-1 MEDIUM 156.0 78.0 review-and-rightsize
Metric query skipped due to budget exhaustion
Heuristic
underutilized_rds 30% Access Denied Missing CloudWatch permissions to read metrics for this resource. analytics-postgres-db
db.t3.large
us-east-1 LOW 0.0 0.0 review-and-rightsize
Unable to measure CPU/storage utilization: missing CloudWatch permissions (AccessDenied).
Heuristic
old_snapshot 50% snap-0123456789abcdef
668 days old
us-east-1 LOW 5.0 5.0 delete-snapshot
Snapshot is older than the retention window.
Heuristic

📁 CSV export available: findings.csv generated alongside this report.