In the AWS ecosystem, CloudFormation is the "safe" default. But as my infrastructure grew to include Cloudflare for edge routing, PagerDuty for alerting, and GitHub for CI/CD, CloudFormation became a silo. Here is the technical breakdown of why I migrated the entire "Spectrum" to HashiCorp Terraform.
1. The State of the Union: State Management
The biggest hurdle in IaC is "drift"—when someone manually changes a security group in the AWS Console.
- CloudFormation manages state internally; if the stack gets out of sync, you often hit the dreaded
UPDATE_ROLLBACK_FAILEDstate. - Terraform stores state in a
tfstatefile (which we store in an S3 bucket with DynamoDB locking). This allows forterraform plan, giving you a dry-run of exactly what will change before a single API call is made.
2. Provider Versatility
A modern DevOps stack isn't just AWS. In my current setup, a single terraform apply handles:
- AWS: Provisioning the EKS cluster and EMR nodes.
- Cloudflare: Updating DNS A-records to point to the new Load Balancer.
- GitHub: Configuring repository secrets for the CI/CD pipeline.
# Example of a Cross-Provider Resource Dependency
resource "aws_lb" "prod_alb" {
name = "prod-alb"
load_balancer_type = "application"
# ...
}
resource "cloudflare_record" "app_dns" {
zone_id = var.cloudflare_zone_id
name = "api"
value = aws_lb.prod_alb.dns_name
type = "CNAME"
proxied = true
}3. The Migration Strategy (The "Import" Trick)
You don't have to rebuild from scratch. Use the terraform import command to bring existing AWS resources into your state file. This allows for a "brownfield" migration where you slowly wrap code around existing infrastructure.