67 / 75 · 08 Infrastructure as Code Testing · Ephemeral Environments← prev⊞ allnext →☰ Read as one page
12.5Cost Control Strategies
Ephemeral environments can be expensive if not managed carefully. A single PR environment with an RDS instance, ECS service, and load balancer costs roughly $5-15/day. With 20 active PRs, that is $100-300/day.
| Strategy | Implementation | Savings |
|---|---|---|
| Auto-destroy after N hours | GitHub Action cron job + terraform destroy |
60-80% |
| Minimal instance sizes | Conditional sizing based on workspace name | 70-90% |
| Shared read-only resources | Reference production VPC, DNS zone via data sources | 20-30% |
| Spot instances for compute | capacity_type = "SPOT" for EKS nodes |
60-70% |
| Scheduled scale-to-zero | Lambda that scales down PR envs outside business hours | 50-60% |
| TTL tags on all resources | Automated cleanup of resources older than 48 hours | Prevents zombie resources |
Auto-Destroy Cron Job
# .github/workflows/cleanup-ephemeral.yml
name: Cleanup Stale Ephemeral Environments
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM UTC
workflow_dispatch:
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Find stale environments
run: |
cd terraform/
terraform workspace list | grep "pr-" | while read ws; do
WS_NAME=$(echo "$ws" | tr -d ' *')
PR_NUM=$(echo "$WS_NAME" | grep -oP '\d+')
# Check if the PR is still open
PR_STATE=$(gh pr view "$PR_NUM" --json state -q '.state' 2>/dev/null || echo "UNKNOWN")
if [ "$PR_STATE" != "OPEN" ]; then
echo "Destroying stale environment: $WS_NAME (PR state: $PR_STATE)"
terraform workspace select "$WS_NAME"
terraform destroy -auto-approve
terraform workspace select default
terraform workspace delete "$WS_NAME"
fi
done
Resource TTL Tags
# Add TTL tags to all ephemeral resources
locals {
common_tags = merge(
{
Team = "platform"
Environment = local.env_name
ManagedBy = "terraform"
},
local.is_ephemeral ? {
EphemeralTTL = timeadd(timestamp(), "48h")
PRNumber = var.pr_number
} : {}
)
}