Complete guide to safely tearing down production AWS infrastructure to avoid ongoing charges, covering automated cleanup, cost optimization, and data preservation strategies.
Welcome to the final part of our comprehensive series on building production-grade microservices on AWS ECS. In this installment, we’ll cover the essential process of safely tearing down your AWS infrastructure to avoid ongoing charges while preserving important data and configurations.
In this cleanup guide, we’ll provide you with:
Understanding the cost implications of your infrastructure is crucial for effective cleanup planning.
| Resource | Configuration | Monthly Cost | Priority |
|---|---|---|---|
| NAT Gateways | 2x Multi-AZ | ~$65 | ⚠️ Critical |
| RDS PostgreSQL | Multi-AZ, db.t3.micro | ~$35 | ⚠️ High |
| ECS Fargate Tasks | 2 Nginx + 2 Flask + 1 Redis | ~$40 | ⚠️ High |
| Application Load Balancer | Internet-facing | ~$20 | ⚠️ Medium |
| Elastic IPs | 2x Unattached | ~$7 | ⚠️ Medium |
| CloudWatch Logs | 7-day retention | ~$2 | ⚠️ Low |
| Data Transfer | ALB to ECS | ~$5 | ⚠️ Low |
| ECR Storage | Container images | ~$1 | ⚠️ Low |
| Total | Complete Infrastructure | ~$175/month | 🚨 Urgent |
Immediate Action Required:
⚠️ IMPORTANT: Follow this exact order to prevent dependency conflicts and ensure complete cleanup:
The safest and most efficient method for complete infrastructure cleanup.
cd terraform
terraform plan -destroy
Review the output carefully. You should see all resources planned for destruction.
Before destroying, create a final snapshot:
aws rds create-db-snapshot \
--db-instance-identifier ecs-microservices-postgres \
--db-snapshot-identifier ecs-microservices-final-snapshot-$(date +%Y%m%d) \
--region ap-south-1
# Wait for snapshot to complete
aws rds wait db-snapshot-completed \
--db-snapshot-identifier ecs-microservices-final-snapshot-$(date +%Y%m%d) \
--region ap-south-1
If you don’t want a final snapshot, update in Terraform:
Edit main.tf and change:
skip_final_snapshot = true
Then apply:
terraform apply -auto-approve
terraform destroy
Type yes when prompted.
This will take 15-20 minutes due to:
# Check ECS clusters
aws ecs list-clusters --region ap-south-1
# Check RDS instances
aws rds describe-db-instances --region ap-south-1
# Check VPCs (should only show default VPC)
aws ec2 describe-vpcs --region ap-south-1
# Check NAT Gateways
aws ec2 describe-nat-gateways --region ap-south-1 \
--filter "Name=state,Values=available"
# Check ALBs
aws elbv2 describe-load-balancers --region ap-south-1
All should return empty or only default resources.
For situations where Terraform is not available or you need granular control over the cleanup process.
Go to ECS → Clusters → ecs-microservices-cluster
Click Services tab
For each service (nginx, flask-app, redis):
0After all tasks stopped, delete services:
⏱️ Time: ~5 minutes
ecs-microservices-alb⏱️ Time: ~2 minutes
ecs-microservices-nginx-tg⏱️ Time: ~1 minute
⚠️ Critical: Create final snapshot first if you need the data!
ecs-microservices-postgres⏱️ Time: ~10-15 minutes
⚠️ This is the most expensive resource! Delete immediately to stop charges.
⏱️ Time: ~5 minutes
⚠️ Note: You can only release EIPs after NAT Gateways are deleted.
⏱️ Time: ~1 minute
ecs-microservices-cluster⏱️ Time: ~2 minutes
ecs-microservices.local⏱️ Time: ~1 minute
/ecs/ecs-microservices/flask-app/ecs/ecs-microservices/nginx/ecs/ecs-microservices/redis/ecs/ecs-microservices/exec⏱️ Time: ~1 minute
⚠️ Only delete if you don’t need the images anymore!
ecs-microservices/flask-appecs-microservices/nginx⏱️ Time: ~1 minute
Wait for NAT Gateways to finish deleting, then:
ecs-microservices-vpcThis will delete:
⚠️ If deletion fails, manually delete in this order:
⏱️ Time: ~5 minutes
ecs-microservices-ecs-task-execution-roleecs-microservices-ecs-task-role⏱️ Time: ~2 minutes
⏱️ Time: ~1 minute
For automated cleanup without Terraform, use this production-ready script.
#!/bin/bash
# Automated cleanup script
set -e
AWS_REGION="ap-south-1"
PROJECT_NAME="ecs-microservices"
echo "🧹 Starting cleanup process..."
# Step 1: Scale down ECS services to 0
echo "⏬ Scaling down ECS services..."
for service in nginx flask-app redis; do
aws ecs update-service \
--cluster ${PROJECT_NAME}-cluster \
--service ${PROJECT_NAME}-${service} \
--desired-count 0 \
--region ${AWS_REGION} \
> /dev/null 2>&1 || echo "Service ${service} not found or already deleted"
done
sleep 30
# Step 2: Delete ECS services
echo "🗑️ Deleting ECS services..."
for service in nginx flask-app redis; do
aws ecs delete-service \
--cluster ${PROJECT_NAME}-cluster \
--service ${PROJECT_NAME}-${service} \
--force \
--region ${AWS_REGION} \
> /dev/null 2>&1 || echo "Service ${service} not found or already deleted"
done
echo "⏳ Waiting for services to be deleted (60 seconds)..."
sleep 60
# Step 3: Use Terraform to destroy everything else
echo "🔥 Running terraform destroy..."
terraform destroy -auto-approve
echo "✅ Cleanup completed!"
echo "💰 Check AWS Console to verify all resources are deleted"
Make it executable and run:
chmod +x cleanup.sh
./cleanup.sh
⚠️ HIGH PRIORITY - Verify these are deleted to avoid charges:
Navigate to Cost Explorer:
Expected Results:
# Check current costs
aws ce get-cost-and-usage \
--time-period Start=2024-01-01,End=2024-01-31 \
--granularity MONTHLY \
--metrics BlendedCost \
--region us-east-1
# Check for running resources
aws ec2 describe-instances --region ap-south-1 --query 'Reservations[*].Instances[*].[InstanceId,State.Name]'
aws rds describe-db-instances --region ap-south-1 --query 'DBInstances[*].[DBInstanceIdentifier,DBInstanceStatus]'
aws ecs list-clusters --region ap-south-1
Error: “The vpc has dependencies and cannot be deleted”
Root Cause: Dependencies still exist in the VPC
Solution: Delete resources in this exact order:
Symptoms: NAT Gateway shows “deleting” for more than 10 minutes
Solution:
Error: “has dependent objects”
Root Cause: Network interfaces or instances still using the security group
Solution:
Symptoms: RDS instance stuck in “deleting” state
Root Cause: Final snapshot creation or Multi-AZ cleanup
Solution:
Common Causes: State drift, resource dependencies, permission issues
Solution:
terraform refreshterraform destroyterraform state rm <resource>terraform destroy againSymptoms: Services remain at desired count despite update
Solution:
--force-new-deploymentFor temporary cost reduction while preserving infrastructure:
1. Stop ECS Services (saves ~$40/month):
# Scale down all services to 0
aws ecs update-service --cluster ecs-microservices-cluster \
--service ecs-microservices-flask-app --desired-count 0 --region ap-south-1
aws ecs update-service --cluster ecs-microservices-cluster \
--service ecs-microservices-nginx --desired-count 0 --region ap-south-1
aws ecs update-service --cluster ecs-microservices-cluster \
--service ecs-microservices-redis --desired-count 0 --region ap-south-1
2. Stop RDS Database (saves ~$35/month):
aws rds stop-db-instance \
--db-instance-identifier ecs-microservices-postgres \
--region ap-south-1
⚠️ Note: RDS auto-starts after 7 days
3. Delete NAT Gateways (saves ~$65/month):
# Delete NAT Gateways (requires Terraform apply to recreate)
aws ec2 delete-nat-gateway --nat-gateway-id <nat-gateway-id> --region ap-south-1
For long-term development use:
1. Use Single-AZ RDS (saves ~$17/month):
2. Use Single NAT Gateway (saves ~$32/month):
3. Reduce ECS Task Counts (saves ~$20/month):
# Start RDS
aws rds start-db-instance \
--db-instance-identifier ecs-microservices-postgres \
--region ap-south-1
# Scale up ECS services
aws ecs update-service --cluster ecs-microservices-cluster \
--service ecs-microservices-redis --desired-count 1 --region ap-south-1
aws ecs update-service --cluster ecs-microservices-cluster \
--service ecs-microservices-flask-app --desired-count 2 --region ap-south-1
aws ecs update-service --cluster ecs-microservices-cluster \
--service ecs-microservices-nginx --desired-count 2 --region ap-south-1
⚠️ HIGH PRIORITY - These actions save the most money:
Before Deletion:
After Cleanup:
| Method | Time Required | Complexity | Recommended For |
|---|---|---|---|
| Terraform Destroy | 15-20 minutes | Low | Production use |
| Manual Console | 30-40 minutes | Medium | Learning/understanding |
| Automated Script | 20-25 minutes | Low | Repetitive cleanup |
🎉 Congratulations! You’ve successfully completed the entire production-grade ECS microservices series:
Remember: AWS bills are prorated, so the sooner you delete resources, the less you pay!
Questions or feedback? Feel free to reach out in the comments below!