Infrastructure as Code
Automate everything with CloudFormation templates and Terraform modules. Compare IaC approaches.
What You'll Learn
You've deployed everything manually and with CloudFormation. Now let's compare the two major IaC approaches and learn Terraform โ the multi-cloud standard.
| Azure | AWS | Notes |
|---|---|---|
ARM Templates | CloudFormation | CloudFormation is the AWS-native IaC |
Bicep | CloudFormation | Bicep is ARM's friendly syntax; CF uses YAML/JSON |
Terraform (azurerm) | Terraform (aws) | Same tool, different provider |
CloudFormation vs Terraform
| Feature | CloudFormation | Terraform |
|---|---|---|
| Provider | AWS only | Multi-cloud |
| Language | YAML / JSON | HCL |
| State | Managed by AWS | Self-managed (S3) |
| Preview | Change Sets | terraform plan |
| Rollback | Automatic | Manual |
| Modules | Nested Stacks | First-class modules |
When to use which? CloudFormation for pure AWS shops needing auto-rollback. Terraform for multi-cloud, better module ecosystem, and team collaboration via Terraform Cloud.
Terraform Basics
Project Structure
terraform/
โโโ main.tf # Root module โ wires everything together
โโโ variables.tf # Input variables
โโโ outputs.tf # Output values
โโโ providers.tf # AWS provider config
โโโ backend.tf # Remote state (S3 + DynamoDB)
โโโ modules/
โโโ vpc/ # Networking module
โโโ rds/ # Database module
โโโ alb/ # Load balancer module
โโโ asg/ # Auto scaling module
โโโ cicd/ # Pipeline moduleThe Terraform Workflow
terraform initโ Download providers and initialize backendterraform planโ Preview what will change (like a CF Change Set)terraform applyโ Create/update the resourcesterraform destroyโ Delete everything
Example: VPC Module in Terraform
Compare this to the CloudFormation YAML you've already seen:
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "${var.project_name}-vpc"
}
}
resource "aws_subnet" "public" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index + 1)
availability_zone = data.aws_availability_zones.available.names[count.index]
map_public_ip_on_launch = true
}
resource "aws_subnet" "private" {
count = 2
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index + 10)
availability_zone = data.aws_availability_zones.available.names[count.index]
}If you've used provider "azurerm" in Terraform, the AWS provider follows the exact same patterns. The main difference is AWS doesn't have a Resource Group concept โ you use tags instead.
State Management
CloudFormation manages state automatically. With Terraform, you must manage it:
terraform {
backend "s3" {
bucket = "aws-sandbox-tf-state-ACCOUNT_ID"
key = "aws-sandbox/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "aws-sandbox-tf-lock" # Prevents concurrent modifications
encrypt = true
}
}Never commit terraform.tfstate to git! It often contains sensitive data (passwords, keys). Always use remote state (S3) for team projects.
Hands-On: Deploy with Terraform
cd terraform
# Initialize
terraform init
# Preview all resources that will be created
terraform plan
# Apply โ creates everything in ~15 minutes
terraform apply
# View what was created
terraform state list
terraform output
# Destroy when done
terraform destroyKey Takeaways
- CloudFormation = AWS-native, auto-rollback, no state management needed
- Terraform = multi-cloud, better module system,
plancommand is superior - Terraform state must be stored remotely (S3 + DynamoDB) for team use
- Both are valid choices โ pick based on your organization's needs