Infrastructure as Code: Terraform vs. CloudFormation
Infrastructure as Code (IaC) is no longer optional. Manually clicking through consoles doesn’t scale. The question is: which tool?
For AWS-centric teams, the choice often comes down to Terraform vs. CloudFormation. Let’s compare.
CloudFormation: AWS Native
CloudFormation is AWS’s built-in IaC service.
Example Template
# cloudformation.yml
AWSTemplateFormatVersion: '2010-09-09'
Description: Simple EC2 instance
Resources:
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t3.micro
ImageId: ami-0123456789abcdef0
SecurityGroups:
- !Ref InstanceSecurityGroup
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow SSH
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Deploy
aws cloudformation create-stack \
--stack-name my-stack \
--template-body file://cloudformation.yml
Strengths
- Native AWS integration: No external tools needed
- Drift detection: Knows when resources change outside CloudFormation
- Stack sets: Deploy to multiple accounts/regions
- Free: No additional cost
- StackSets: Multi-account, multi-region deployments
Weaknesses
- AWS only: Can’t manage GCP, Azure, or other providers
- Verbose syntax: YAML/JSON templates get long
- Limited logic: Conditions and loops are awkward
- Slow updates: New services take time to appear
Terraform: Provider Agnostic
Terraform is HashiCorp’s multi-cloud IaC tool.
Example Configuration
# main.tf
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "main" {
ami = "ami-0123456789abcdef0"
instance_type = "t3.micro"
vpc_security_group_ids = [aws_security_group.main.id]
}
resource "aws_security_group" "main" {
name = "allow_ssh"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Deploy
terraform init
terraform plan
terraform apply
Strengths
- Multi-cloud: AWS, GCP, Azure, and 1000+ providers
- HCL syntax: More readable than YAML/JSON
- Powerful expressions: Loops, conditionals, functions
- State management: Track resources across runs
- Module ecosystem: Reusable components
- Plan before apply: See changes before making them
Weaknesses
- State management complexity: State must be stored carefully
- Provider lag: New AWS features may take weeks
- Learning curve: HCL and state concepts take time
- Cost: Terraform Cloud/Enterprise are paid products
Head-to-Head Comparison
| Factor | CloudFormation | Terraform |
|---|---|---|
| Multi-cloud | ❌ AWS only | ✅ 1000+ providers |
| Learning curve | Lower | Higher |
| Syntax | YAML/JSON | HCL |
| State management | AWS handles | You manage |
| Drift detection | ✅ Built-in | Partial |
| Speed of updates | Slower | Faster |
| Loops/conditionals | Limited | Powerful |
| Cost | Free | Free (OSS) / Paid (Cloud) |
When to Choose CloudFormation
- 100% AWS, staying that way: No multi-cloud plans
- Minimal tooling: Fewer moving parts
- AWS Organizations: Stack sets are powerful
- CDK interest: AWS CDK generates CloudFormation
When to Choose Terraform
- Multi-cloud or hybrid: Any non-AWS resources
- Complex logic: Dynamic resource generation
- Team expertise: Already using Terraform elsewhere
- Module reuse: Share infrastructure across projects
Can You Use Both?
Yes! Some teams use:
- CloudFormation for foundational AWS resources
- Terraform for application-level infrastructure
But beware of managing the same resources with both—that leads to drift.
State Management Deep Dive
Terraform’s state is critical. Store it safely:
# backend.tf
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "prod/terraform.tfstate"
region = "us-west-2"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
CloudFormation doesn’t have this problem—AWS manages state internally.
Modern Alternatives
Worth considering:
- AWS CDK: Write CloudFormation in TypeScript/Python
- Pulumi: Write infrastructure in real programming languages
- Crossplane: Kubernetes-native infrastructure management
My Recommendation
For most teams: Start with Terraform. The multi-cloud flexibility and HCL syntax are worth the state management overhead.
For pure AWS shops: CloudFormation (or CDK) is perfectly valid. One less tool to manage.
Either way: Pick one and stick with it. Consistency matters more than the specific choice.
Final Thoughts
The IaC landscape is mature. Both tools are production-ready and well-supported. Your choice depends on your cloud strategy and team preferences.
The important thing is using IaC at all. Manual infrastructure is technical debt waiting to happen.
Infrastructure should be code. Period.