Automatically identify and eliminate cloud waste across AWS, GCP, and Azure
Stop paying for forgotten resources. CloudWarden finds unattached volumes, stopped instances, idle IPs, and orphaned snapshots that silently drain your cloud budget.
Cloud waste is everywhere:
- Developers spin up resources for testing and forget them
- Projects end but resources remain
- Engineers leave and their infrastructure stays behind
- Result: 5-15% of your cloud bill is wasted on zombie resources
Before: $10,000/month cloud bill
After: $8,500/month cloud bill
Savings: $1,500/month = $18,000/year
Time to implement: < 1 hour
CloudWarden v1.3.0+ - All advertised features are fully implemented and production-ready:
- ✅ AWS Support: 16 resource types - fully supported (default build)
- ✅ Azure Support: 6 resource types - fully supported (default build)
- ✅ GCP Support: 6 resource types - fully implemented (requires
-tags=gcpbuild flag) - ✅ PDF Reports: Complete implementation with charts and analytics
- ✅ REST API: 10+ endpoints for programmatic access
- ✅ Scheduler: Cron-based automation with policy engine
- ✅ Approval Workflows: Email-based approvals with secure tokens
- ✅ Audit Logging: JSONL-based compliance trails
- ✅ Rate Limiting: Token bucket with exponential backoff
- ✅ Progress Bars: Visual feedback for all long operations
- ✅ Webhooks: Real-time notifications for custom integrations
- ✅ Email Notifications: HTML templates with SMTP support
See ROADMAP.md for detailed implementation status and future plans.
- Complete Multi-Cloud Support: AWS (16 types), Azure (6 types), GCP (6 types) = 28 total resource types
- AWS Resources:
- Unattached EBS volumes
- Stopped EC2 instances (>30 days)
- Unassociated Elastic IPs
- Orphaned EBS snapshots
- Idle NAT Gateways (with CloudWatch traffic monitoring)
- Unused Load Balancers (with CloudWatch request count tracking)
- Old RDS snapshots
- CloudWatch Log Groups (old/large logs)
- Lambda functions (not invoked in 90+ days)
- S3 buckets (empty or very old)
- DynamoDB tables (no reads/writes with CloudWatch metrics)
- ECS clusters (no active services or tasks)
- EKS clusters (no node groups)
- Elasticache clusters (low CPU utilization)
- Redshift clusters (paused or unused)
- Classic ELB (deprecated load balancers)
- Azure Resources:
- Stopped/Deallocated Virtual Machines
- Unattached Managed Disks
- Unassociated Public IPs
- Unused Load Balancers
- Old Snapshots
- Idle NAT Gateways
- GCP Resources (requires
-tags=gcpbuild):- Stopped Compute Engine instances
- Unattached Persistent Disks
- Unassigned Static IPs
- Idle Cloud NAT gateways
- Unused Load Balancers
- Old Snapshots (>90 days)
- Multi-region scanning (parallel, fast)
- Age tracking and cost estimation across all clouds
- Real-time Metrics Analysis:
- NAT Gateway traffic monitoring (BytesIn/BytesOut)
- Load Balancer request count tracking
- Lambda function invocation statistics
- DynamoDB read/write capacity monitoring
- Elasticache CPU utilization tracking
- Identifies truly idle resources vs. occasionally used ones
- 7-day rolling window for accurate detection
- Reduces false positives with actual usage data
- Calculate monthly waste per resource
- Annual cost projections
- Aggregate reports by team, project, or type
- Historical Trend Analysis:
- Week-over-week and month-over-month comparisons
- Track resource count changes and cost trends
- Identify improving vs. worsening waste patterns
- Automatic scan history storage for trend tracking
- Executive Summary Dashboard:
- High-level overview for management
- Top waste categories by cost and percentage
- High-confidence savings identification
- Actionable recommendations
- Resource breakdown by cloud provider and type
- Cost Savings Tracking:
- Track actual savings from cleanup operations
- Monthly and annual savings calculations
- Savings by cloud provider, resource type, and region
- Cleanup history with detailed summaries
- Cross-Cloud Comparison: Compare waste across AWS, Azure, and GCP
- Multi-Cloud Unified Reporting: Single view of all cloud waste
- Dry-run mode by default (no accidental deletions)
- Grace period tagging (7-day warning before deletion)
- Automatic backups before deletion
- Tag-based exclusions (
DoNotDelete=true) - Production resource protection
- Summary: Quick terminal overview
- CSV: For Excel and finance teams
- JSON: For API integration
- HTML: Interactive dashboards
- PDF: Professional executive reports with analytics and charts
- Email: SMTP-based notifications with HTML reports
- Slack: Channel-specific updates and alerts
- Webhooks: Custom webhook integrations for real-time notifications
- High-cost resource alerts
- Cleanup summaries
- Team-specific reports
- Built-in Scheduler: Cron-based job scheduling for periodic scans, cleanups, and reports
- Flexible Schedules: Support for cron expressions, predefined schedules (@daily, @weekly), and duration formats
- Automated Cleanup Workflows: Policy-based auto-deletion with safety controls
- Policy Engine: Configure auto-approval criteria (cost thresholds, age requirements, production exclusions)
- Grace Period System: Tag resources before deletion with configurable warning periods
- Job Management: Add, remove, enable/disable, and trigger jobs on-demand
- REST API: Full-featured HTTP API for programmatic access
- Webhook Support: Real-time notifications for custom integrations
- Multi-Account Scanning: AWS Organizations support with automatic account discovery
- GitHub Actions: Pre-built workflows for CI/CD and scheduled scans
- Grafana/Prometheus: Real-time dashboards and metrics
- Terraform: Infrastructure-as-Code modules for automated deployment
- Audit Logging: Comprehensive JSONL-based audit trails for all operations
- Track all scans, cleanups, and deletions
- Daily log rotation with automatic archival
- Query capabilities for compliance reporting
- Tamper-evident logging format
- Email Approval Workflow: Multi-approver email-based approvals
- Secure token-based approval/rejection links
- HTML email templates with resource summaries
- Configurable expiration timeouts
- Multi-stage approval requirements
- Rate Limiting: Intelligent API throttling and retry logic
- Token bucket rate limiting for API calls
- Exponential backoff retry with configurable delays
- Cloud-specific retry configurations (AWS, Azure, GCP)
- Context-aware retry handling
- Progress Bars: Visual feedback for long-running operations
- Region-by-region scan progress tracking
- Multi-account scanning progress
- Resource cleanup progress indicators
- Configurable progress display options
# Install via Go (default build with AWS and Azure support)
go install github.com/deepcost/CloudWarden/cmd/scanner@latest
# Or build from source
git clone https://github.com/deepcost/CloudWarden.git
cd CloudWarden
make build
sudo cp build/cloudwarden /usr/local/bin/Building with GCP Support:
By default, CloudWarden builds with AWS and Azure support. To enable GCP scanning:
# Build with GCP support using build tag
git clone https://github.com/deepcost/CloudWarden.git
cd CloudWarden
go mod download # Download dependencies including GCP SDK
go build -tags=gcp -o cloudwarden ./cmd/scanner
sudo cp cloudwarden /usr/local/bin/The GCP scanner is implemented as an optional build-time dependency to keep the default binary size smaller for users who only need AWS/Azure support.
- Go 1.20+ (for building from source)
- Cloud credentials configured:
- AWS: AWS credentials configured (for AWS scanning)
- GCP:
GOOGLE_APPLICATION_CREDENTIALSenvironment variable or Application Default Credentials - Azure: Azure credentials configured via Azure CLI or environment variables
- Appropriate IAM/permissions (see guide)
# Scan all AWS regions (safe, read-only)
cloudwarden scan --cloud aws --output scan-results.json
# Scan GCP project
cloudwarden scan --cloud gcp --project-id my-project-123 --output gcp-results.json
# Scan Azure subscription
cloudwarden scan --cloud azure --subscription-id abc-123 --output azure-results.json
# Scan all clouds at once
cloudwarden scan --cloud all --output multi-cloud-results.jsonOutput:
🔍 Starting cloud waste scan...
Cloud Provider: aws
Mode: Dry-run (safe)
📡 Scanning AWS resources...
Found 247 total resources
🔬 Analyzing resources...
Identified 127 unused resources
💰 Cost Analysis:
Monthly waste: $3,456.80
Annual projection: $41,481.60
📊 Resource Breakdown:
ebs_volume: 89 resources ($1,890.00/month)
ec2_instance: 23 resources ($1,057.00/month)
elastic_ip: 15 resources ($54.00/month)
✅ Report saved to: scan-results.json
# View summary in terminal
cloudwarden report --input scan-results.json --format summary
# Generate CSV for finance team
cloudwarden report --input scan-results.json --format csv --output waste-report.csv
# Create HTML dashboard
cloudwarden report --input scan-results.json --format html --output dashboard.html
# Generate PDF executive report
cloudwarden report --input scan-results.json --format pdf --output executive-report.pdfPDF Report Features:
- Professional multi-page layout
- Executive summary with key metrics
- Resource breakdown by type with cost percentages
- Top 20 most expensive resources
- Advanced analytics (if enabled during scan)
- High-confidence savings identification
- Recommended actions and insights
# See what would be deleted (dry-run)
cloudwarden cleanup --input scan-results.json --dry-run
# Actually delete resources with backup (recommended)
cloudwarden cleanup --input scan-results.json --confirm --backup
# Use grace period (tag resources, wait, then delete)
cloudwarden cleanup --input scan-results.json --confirm --grace-period 7
# Send Slack notification after cleanup
cloudwarden cleanup --input scan-results.json --confirm \
--slack-webhook "https://hooks.slack.com/services/YOUR/WEBHOOK" \
--slack-channel "#cloud-cleanup"Safety Features:
--dry-run: Preview deletions without making changes (default)--backup: Create snapshots/AMIs before deletion (default: true)--grace-period N: Tag resources for N days before deleting--confirm: Required flag to actually delete resources
#### 4. Analytics & Trend Analysis
CloudWarden includes powerful analytics features enabled by default:
```bash
# Scan with analytics (default)
cloudwarden scan --cloud aws --output scan.json
# This provides:
# - Executive Summary with top waste categories
# - Trend Analysis (week-over-week or month-over-month)
# - High-confidence savings identification
# - Actionable recommendations
Example Output:
📋 Executive Summary:
Total Waste Identified: $3,456.80/month ($41,481.60/year)
Resources: 127 total, 89 high confidence
High Confidence Savings: $2,890.00/month
Top Waste Categories:
1. Storage: 89 resources ($1,890.00/month, 54.7%)
2. Compute: 23 resources ($1,057.00/month, 30.6%)
3. Network: 15 resources ($509.80/month, 14.7%)
Recommended Actions:
• Immediately review 89 high-confidence resources (potential $2,890.00/month savings)
• Focus on Storage resources - 89 resources costing $1,890.00/month (54.7% of total waste)
📊 Trend Analysis:
Comparison Period: week-over-week
Previous Scan: 2025-01-08
Current Scan: 2025-01-15
Resource Count: ↑ +12 (10.4%)
Cost: ↑ $+245.80 (7.7%)
New Resources: 18
Removed Resources: 6
Overall Trend: worsening
Scan History:
- Scans are automatically saved to
~/.cloudwarden/history/ - Enables week-over-week and month-over-month comparisons
- Custom history directory:
--history-dir /path/to/history - Disable analytics:
--analytics=false
CloudWarden includes a built-in scheduler for automated periodic scans, cleanups, and reports:
# Start scheduler with configured jobs from config.yaml
cloudwarden schedule start --config config.yamlThe scheduler will run jobs based on your configuration:
scanner:
scheduler:
enable_daily_scans: true # Daily waste scans at midnight
enable_weekly_cleanup: true # Weekly automated cleanup
enable_weekly_reports: true # Weekly cost reportsExample Output:
🕐 Starting CloudWarden Scheduler...
📋 Loaded 3 scheduled jobs:
• daily-scan (scan) - @daily
Next run: 2025-01-16T00:00:00Z
Description: Daily cloud waste scan
• weekly-cleanup (cleanup) - @weekly
Next run: 2025-01-20T00:00:00Z
Description: Weekly automated cleanup
• weekly-report (report) - @weekly
Next run: 2025-01-20T00:00:00Z
Description: Weekly cost report generation
✅ Scheduler started successfully
Press Ctrl+C to stop the scheduler...
# Add a daily scan job
cloudwarden schedule add \
--job-id daily-scan \
--job-type scan \
--schedule "@daily" \
--description "Daily cloud waste scan" \
--config config.yaml
# Add cleanup job every 6 hours
cloudwarden schedule add \
--job-id cleanup-6h \
--job-type cleanup \
--schedule "0 */6 * * *" \
--description "Cleanup every 6 hours" \
--config config.yaml
# Add weekly report on Mondays at 9 AM
cloudwarden schedule add \
--job-id monday-report \
--job-type report \
--schedule "0 9 * * 1" \
--description "Weekly Monday morning report" \
--config config.yaml- Predefined schedules:
@hourly,@daily,@weekly,@monthly - Duration format:
30m,1h,6h,24h - Cron expressions:
0 9 * * *(9 AM daily),0 0 * * 1(Monday midnight)
# List all scheduled jobs
cloudwarden schedule list
# Check scheduler status
cloudwarden schedule status
# Run a job immediately (outside of schedule)
cloudwarden schedule run-now --job-id daily-scan
# Remove a job
cloudwarden schedule remove --job-id daily-scanConfigure automated cleanup with safety policies:
scanner:
cleanup:
enabled: true
dry_run: false # Set to false for actual deletion
auto_approve:
max_monthly_cost: 10.00 # Auto-approve resources <$10/month
min_age_days: 30 # Only delete resources >30 days old
exclude_prod: true # Never auto-delete prod resources
safety:
grace_period_days: 7 # Tag resources 7 days before deletion
create_backups: true # Always create backups first
max_deletions_per_run: 50 # Safety limitHow it works:
- Scheduler runs cleanup workflow on schedule
- Resources meeting criteria are auto-approved:
- Cost ≤
max_monthly_cost - Age ≥
min_age_days - Not tagged as production (if
exclude_prod: true)
- Cost ≤
- Resources are tagged with grace period warning
- After grace period, resources are backed up and deleted
- Notifications sent to configured channels
# Scan only DataScience team's resources
cloudwarden scan --cloud aws \
--filter-tag "Team=DataScience" \
--output datascience-waste.json# More aggressive scanning (shorter thresholds)
cloudwarden scan --cloud aws \
--ebs-threshold 3 \
--stopped-instance-threshold 7 \
--elastic-ip-threshold 1# Use configuration file for complex setups
cloudwarden scan --cloud aws --config my-config.yamlSee examples/config.yaml for configuration options.
Slack notifications can be configured in the YAML configuration file:
notifications:
slack:
enabled: true
webhook: "https://hooks.slack.com/services/YOUR/WEBHOOK"
channel: "#cloud-costs"CloudWarden includes a full-featured REST API for programmatic access and integrations:
# Start API server on default port (8080)
cloudwarden api --config config.yaml
# Start on custom port with webhook notifications
cloudwarden api --port 9000 --webhook https://hooks.example.com/cloudwardenAvailable Endpoints:
# Health check
GET http://localhost:8080/health
# Scan endpoints
POST http://localhost:8080/api/v1/scan/aws
POST http://localhost:8080/api/v1/scan/azure
POST http://localhost:8080/api/v1/scan/gcp
POST http://localhost:8080/api/v1/scan/all
# Analysis endpoints
POST http://localhost:8080/api/v1/analyze/cost
POST http://localhost:8080/api/v1/analyze/trends
POST http://localhost:8080/api/v1/analyze/multicloud
# Webhook management
POST http://localhost:8080/api/v1/webhooks/register
POST http://localhost:8080/api/v1/webhooks/testExample Usage:
# Trigger AWS scan via API
curl -X POST http://localhost:8080/api/v1/scan/aws
# Register a webhook for notifications
curl -X POST http://localhost:8080/api/v1/webhooks/register \
-H "Content-Type: application/json" \
-d '{"url": "https://hooks.slack.com/services/YOUR/WEBHOOK"}'
# Multi-cloud comparison
curl -X POST http://localhost:8080/api/v1/analyze/multicloud \
-H "Content-Type: application/json" \
-d @multi-cloud-scan-results.jsonWebhook Notifications:
The API server can send real-time notifications to your webhook URL when:
- Scans complete
- High-cost resources detected
- Cleanup operations finish
- Errors occur
Webhook payload example:
{
"event_type": "scan_completed",
"timestamp": "2025-01-16T10:30:00Z",
"cloud_provider": "aws",
"total_resources": 127,
"total_monthly_cost": 3456.80,
"total_annual_cost": 41481.60
}| Resource Type | Detection Criteria | Default Threshold |
|---|---|---|
| EBS Volumes | Unattached state | 7 days |
| EC2 Instances | Stopped state | 30 days |
| Elastic IPs | Unassociated | 1 day |
| EBS Snapshots | Orphaned (source deleted) | 90 days |
| NAT Gateways | Idle/unused | 30 days |
| Load Balancers | No traffic | 30 days |
| RDS Snapshots | Manual snapshots, old | 90 days |
| CloudWatch Log Groups | Old/large logs, no activity | 90 days |
| Lambda Functions | Not invoked recently | 90 days |
| S3 Buckets | Empty or very old | 180 days |
| DynamoDB Tables | No reads/writes in 14 days | 30 days |
| Resource Type | Detection Criteria | Default Threshold |
|---|---|---|
| Compute Engine Instances | Stopped/Terminated state | 30 days |
| Persistent Disks | Unattached state | 7 days |
| Static IP Addresses | Reserved/Unassigned | 1 day |
| Cloud NAT Gateways | Idle configurations | 30 days |
| Load Balancers | No backend instances | 30 days |
| Disk Snapshots | Age-based detection | 90 days |
| Resource Type | Detection Criteria | Default Threshold |
|---|---|---|
| Virtual Machines | Stopped/Deallocated state | 30 days |
| Managed Disks | Unattached state | 7 days |
| Public IP Addresses | Unassociated | 1 day |
| Load Balancers | No backend pool instances | 30 days |
| Disk Snapshots | Age-based detection | 90 days |
| NAT Gateways | No associated subnets | 30 days |
scanner:
cloud_provider: aws
regions: all # or specific: ['us-east-1', 'us-west-2']
thresholds:
ebs_volume_days: 14
stopped_instance_days: 45
elastic_ip_days: 2
exclusions:
- tag: "DoNotDelete=true"
- tag: "Environment=production"
- name_pattern: "^prod-.*"
cleanup:
enabled: true
grace_period_days: 7
create_backups: true
max_deletions_per_run: 50
notifications:
slack:
enabled: true
webhook: "https://hooks.slack.com/services/YOUR/WEBHOOK"
channel: "#cloud-costs"- ✅ Stop paying for forgotten test resources
- ✅ Clean up after departed engineers
- ✅ Automated hygiene, zero manual work
- ✅ Team accountability via tagging
- ✅ 5-15% immediate cost reduction
- ✅ Monthly trending and forecasting
- ✅ CSV reports for analysis
- ✅ ROI tracking
- ✅ Measurable cost savings
- ✅ Improved cloud governance
- ✅ Better resource hygiene culture
- ✅ Compliance and audit trails
- Problem: No visibility into unused resources
- Result: Found $6,890/month in waste
- Action: Cleaned up 76% ($5,234/month saved)
- Annual Savings: ~$50,000
- Problem: Waste scattered across organization
- Result: Identified $234K/year in waste
- Action: 80% cleanup rate with team accountability
- Total Value: $187K savings + $30K labor savings
- Installation Guide: Detailed setup instructions
- Usage Guide: Examples and workflows
- Architecture: Technical design and internals
- Contributing: Development and release process
Q: Will this delete my production resources? A: No. The tool runs in dry-run mode by default and has multiple safeguards:
- Tag-based exclusions (production tags)
- Grace period (7 days default)
- Backups before deletion
- Confirmation required
Q: How much time does it take to set up? A: < 10 minutes for basic scanning. Advanced features (automated cleanup, Slack) take 30-60 minutes.
Q: What permissions does it need? A: Read-only permissions for scanning. Delete permissions only needed for cleanup. See IAM permissions guide.
Q: Can it scan multiple AWS accounts? A: Yes! CloudWarden supports multi-account scanning via AWS Organizations with automatic account discovery and role assumption.
Q: Is my data secure? A: Yes. All scanning happens locally within your infrastructure. No data is sent externally (except Slack notifications if configured).
Q: How often should I run scans? A: Weekly for most teams. Daily for large organizations or high-burn environments.
See ROADMAP.md for the complete roadmap.
- ✅ AWS resource scanning (11 resource types)
- ✅ Cost estimation engine with recommendations
- ✅ Multi-format reports (CSV, JSON, HTML, Summary)
- ✅ Slack notifications
- ✅ Email notifications
- ✅ Backup before deletion
- ✅ Grace period tagging system
- ✅ Multi-region scanning
- ✅ Region filtering (include/exclude)
Target: Q1 2025
- ✅ CloudWatch Log Groups scanner
- ✅ Lambda Functions scanner
- ✅ S3 Buckets scanner
- ✅ DynamoDB tables (no reads/writes, CloudWatch metrics)
- ✅ Retry logic for API throttling
- ✅ Structured logging (JSON format)
- 🔄 Progress bars for scans
- 🔄 Parallel region optimization
- 📋 ECS/EKS unused clusters
- 📋 Elasticache clusters (low utilization)
- 📋 Redshift clusters (paused/unused)
- 📋 PDF report generation
- 📋 Trend analysis (week/month-over-month)
- ✅ GCP support (6 resource types: Compute Engine, Disks, Static IPs, NAT, Load Balancers, Snapshots)
- ✅ Azure support (6 resource types: VMs, Disks, Public IPs, NAT, Load Balancers, Snapshots)
- ✅ Unified cost reporting across clouds
- ✅ Multi-cloud comparison and analysis
Target: Q3 2025
- Built-in scheduler with cron support
- GitOps integration (PR-based approvals)
- REST API for programmatic access
- Terraform provider
- Kubernetes operator
Target: Q4 2025
- Multi-tenancy and RBAC
- Audit logging and compliance reporting
- Advanced analytics and ML-based anomaly detection
- Enterprise integrations (JIRA, ServiceNow, PagerDuty)
We welcome contributions! See CONTRIBUTING.md for:
- Development setup
- Code style guidelines
- Testing requirements
- Release process
Apache 2.0 - See LICENSE for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: https://docs.deepcost.ai
Created by the DeepCost team to help organizations reduce cloud waste.
Start saving today:
go install github.com/deepcost/CloudWarden/cmd/scanner@latest
cloudwarden scan --cloud aws⭐ If this tool saves you money, please star the repo!