How CostCutter Works
CostCutter uses a dependency-aware execution model to safely delete AWS resources in the correct order.
Overview
flowchart LR
CONFIG["Load Config<br/>(YAML/TOML)"] --> GRAPH["Build Graph<br/>(Dependencies)"] --> EXECUTE["Execute Tasks<br/>(In Order)"]
Execution Flow
1. Configuration Loading
CostCutter loads settings from multiple sources in precedence order:
- CLI arguments (highest priority)
- Environment variables (
COSTCUTTER_*) - Project config file (
costcutter.yaml) - Global config file (
~/.config/costcutter/config.toml) - Built-in defaults (lowest priority)
2. AWS Session Initialization
A boto3 session is created using:
- Configured AWS profile, or
- Explicit access keys, or
- Default credential chain
3. Resource Discovery
For each enabled service and region:
- Call AWS
Describe*APIs to list resources - Build a list of resources to delete
- Record discovered resources in the reporter
4. Dependency Graph Construction
CostCutter builds a directed acyclic graph (DAG) where:
- Nodes = Resources to delete (e.g.,
ec2/instances/us-east-1) - Edges = Dependencies (e.g., instances must be deleted before volumes)
5. Topological Sort
The graph is sorted to determine execution order:
flowchart TB
EB_ENV["EB Environments"] --> EC2_INST["EC2 Instances"]
EB_ENV --> EC2_SNAP["EC2 Snapshots"]
EB_ENV --> EC2_KEYS["EC2 Key Pairs"]
EC2_INST --> VOLUMES["Volumes"]
EC2_INST --> EIPS["Elastic IPs"]
EC2_INST --> SG["Security Groups"]
SG --> EB_APP["EB Applications"]
EB_APP --> S3["S3 Buckets"]
6. Staged Execution
Tasks are grouped into stages. Within each stage:
- Tasks run in parallel (controlled by
max_workers) - Each task calls the resource handler
- Individual resource deletions run in parallel (controlled by
resource_max_workers)
Dry-Run Mode
When dry_run: true (the default):
| Action | Dry-Run | Live |
|---|---|---|
| Resource discovery | ✅ Yes | ✅ Yes |
| Dependency graph | ✅ Built | ✅ Built |
AWS Describe calls |
✅ Yes | ✅ Yes |
AWS Delete calls |
❌ No | ✅ Yes |
| Reporting | ✅ "Would delete" | ✅ "Deleted" |
AWS APIs often support a DryRun parameter. CostCutter uses this to validate that deletion would succeed without executing.
Error Handling
Retries
CostCutter handles transient failures:
- Failed tasks are collected during each stage
- After all stages complete, failed tasks are retried once
- Exponential backoff is used for AWS rate limits
Rate Limiting
AWS API rate limits are handled with:
- Configurable parallelism (
max_workers,resource_max_workers) - Automatic retry with backoff
- Pagination for large resource lists
Failure Modes
| Failure Type | Behavior |
|---|---|
| API rate limit | Retry with backoff |
| Permission denied | Log error, continue with other resources |
| Resource not found | Skip (may have been deleted by cascade) |
| Dependency conflict | Retry in deferred stage |
Parallelism
Two levels of parallelism:
Stage-Level (max_workers)
Controls how many resource types process simultaneously:
flowchart TB
subgraph Stage1["Stage 1 (3 parallel)"]
S1A["EC2 Instances"]
S1B["EC2 Snapshots"]
S1C["EC2 Key Pairs"]
end
subgraph Stage2["Stage 2 (3 parallel)"]
S2A["EC2 Volumes"]
S2B["EC2 EIPs"]
S2C["EC2 Security Groups"]
end
Stage1 --> Stage2
Resource-Level (resource_max_workers)
Controls how many individual resources delete simultaneously:
EC2 Instances handler:
[instance-1, instance-2, instance-3, ...] ← 10 parallel (default)
Reporting
CostCutter tracks all events:
- Console: Live table showing recent events
- Summary: Aggregated counts at the end
- CSV: Optional export to file for auditing
Each event records:
- Timestamp
- Region
- Service and resource type
- Action (catalog, delete)
- Resource ARN
- Status and metadata