Terraform vs CloudFormation: Complete Guide 2026
If you're provisioning AWS infrastructure, you'll face this choice sooner or later: Terraform or CloudFormation? Both are mature, production-proven tools. The right answer depends on your team's existing skills, your cloud strategy, and how you plan to scale. This guide covers every dimension of the comparison so you can make an informed decision.
Quick Answer
- Choose Terraform if you use or plan to use multiple cloud providers, prefer a clean declarative language, or value a large ecosystem of community modules.
- Choose CloudFormation if you're 100% AWS-native, need tight AWS service integrations the day they launch, or are in a regulated environment where AWS-managed tooling is preferred.
What Is Terraform?
Terraform is an open-source IaC tool by HashiCorp (now part of IBM). It uses HashiCorp Configuration Language (HCL) to describe infrastructure across 1,700+ providers — AWS, Azure, GCP, Kubernetes, Datadog, GitHub, and more. Terraform manages a state file that tracks what it has created, enabling it to compute a diff and apply only the changes needed.
What Is CloudFormation?
AWS CloudFormation is Amazon's native IaC service. Templates are written in YAML or JSON and describe AWS resources. CloudFormation is fully managed by AWS — no state file to manage, no binary to install. It's deeply integrated with AWS: new services often get CloudFormation support the same day they launch.
Syntax Comparison
Provisioning an S3 bucket with versioning enabled:
Terraform (HCL)
resource "aws_s3_bucket" "app_data" {
bucket = "my-app-data-bucket"
tags = {
Environment = "production"
Project = "my-app"
}
}
resource "aws_s3_bucket_versioning" "app_data" {
bucket = aws_s3_bucket.app_data.id
versioning_configuration {
status = "Enabled"
}
}
CloudFormation (YAML)
Resources:
AppDataBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: my-app-data-bucket
VersioningConfiguration:
Status: Enabled
Tags:
- Key: Environment
Value: production
- Key: Project
Value: my-app
Both are readable. HCL tends to feel more like a programming language; CloudFormation YAML is more verbose but familiar to anyone who knows AWS documentation.
State Management
Terraform State
Terraform stores a terraform.tfstate file that maps your configuration to real infrastructure. This must be stored remotely in a team environment — typically S3 with DynamoDB locking:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "production/terraform.tfstate"
region = "ap-south-1"
dynamodb_table = "terraform-state-lock"
encrypt = true
}
}
State is both a superpower (enables precise diffs and dependency tracking) and a liability (must be protected, can get out of sync if resources are changed outside Terraform).
CloudFormation State
CloudFormation has no state file. AWS manages the stack state internally. This is simpler operationally — there's nothing to lose or corrupt. The trade-off is less flexibility: you can't easily import existing resources that weren't created by CloudFormation.
Key Differences at a Glance
The table below summarises the most important decision-making dimensions:
| Dimension | Terraform | CloudFormation |
|---|---|---|
| Language | HCL (clean, expressive) | YAML / JSON (verbose) |
| Multi-cloud | Yes — 1,700+ providers | AWS only |
| State management | Self-managed (S3 + DynamoDB) | AWS-managed |
| AWS service coverage | Slight lag on new services | Day-one support |
| Drift detection | terraform plan (compare state to reality) |
Built-in stack drift detection |
| Module ecosystem | Terraform Registry (thousands) | AWS CloudFormation Registry |
| Testing | Terratest, terraform test | cfn-lint, TaskCat |
| Cost | Open source (Terraform Cloud optional) | Free (pay for resources created) |
Drift Detection
Drift happens when someone changes infrastructure outside of your IaC tool — via the AWS console, CLI, or another automation.
Terraform: Run terraform plan to see the diff between your state file and the real infrastructure. Terraform will show what has drifted and what it will do to fix it.
CloudFormation: Has a native "Detect Drift" button in the console, or via CLI: aws cloudformation detect-stack-drift --stack-name my-stack. It compares the stack's expected configuration to actual resource properties.
Both tools handle drift detection, but Terraform's approach is more integrated into the normal workflow (you run plan every time anyway), while CloudFormation's is a separate explicit action.
Multi-Cloud Scenarios
If your infrastructure spans AWS and Azure, or AWS and Cloudflare, or AWS and Datadog — Terraform wins clearly. You use the same language, the same workflow, and the same state management across all providers. CloudFormation simply cannot manage non-AWS resources.
Example: managing an EKS cluster (AWS) and its DNS in Cloudflare with a single Terraform root module:
module "eks_cluster" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = "production"
# ...
}
resource "cloudflare_record" "api" {
zone_id = var.cloudflare_zone_id
name = "api"
value = module.eks_cluster.cluster_endpoint
type = "CNAME"
}
Importing Existing Resources
Terraform: Use terraform import to bring existing resources under Terraform management, or the newer terraform state import block syntax. Tools like Terraformer can auto-generate HCL from existing AWS resources.
CloudFormation: Supports resource import for many (not all) resource types via the IMPORT change set operation. It's functional but more limited than Terraform's approach.
CI/CD Integration
Both tools integrate well with CI/CD pipelines.
Terraform: Atlantis is the de facto standard for PR-based Terraform workflows — it runs terraform plan on every PR and posts the output as a comment, then runs terraform apply on merge. You can also use GitHub Actions directly. See our post on provisioning AWS with Terraform for a full example.
CloudFormation: AWS CodePipeline with a CloudFormation deploy action is the native option. GitHub Actions also has an official CloudFormation deploy action from AWS.
Our Recommendation
In practice, we default to Terraform for almost all client engagements. The reasons:
- Teams already familiar with one cloud rarely stay on one cloud forever
- HCL is genuinely more readable than CloudFormation YAML at scale
- The Terraform Registry's module ecosystem is significantly larger
- State-based planning gives engineers clearer visibility into what will change
- Terraform's provider ecosystem covers the full tech stack, not just AWS
The main case for CloudFormation is when a team is deep inside the AWS ecosystem, uses AWS CDK (which compiles to CloudFormation), needs day-one support for brand-new AWS services, or has compliance requirements that mandate AWS-native tooling.
The best IaC tool is the one your team will actually use consistently. Both Terraform and CloudFormation are excellent — don't let perfect be the enemy of done.
Need help choosing or migrating?
Our Terraform automation service covers greenfield setups and ClickOps-to-IaC migrations. We've done both Terraform and CloudFormation at scale.
Automate Your Deployments