IaC · Terraform · CloudFormation

Terraform vs CloudFormation: which should you use on AWS?

Terraform vs CloudFormation: which should you use on AWS?

Both give you infrastructure-as-code on AWS. The right choice depends on multi-cloud plans, team skills, and how much ecosystem you want. Here is the honest breakdown, including the licence question everyone now has to answer.

The short answer

Choose Terraform or OpenTofu if you value multi-cloud portability, a huge module ecosystem, and readable HCL. Choose CloudFormation if you are all-in on AWS, want AWS-managed state and native drift detection with zero extra tooling, and value having new services available on launch day.

The state question is the real difference

Most comparisons lead with syntax. Syntax is the least important difference. State ownership is the one that changes how your team works.

CloudFormation keeps state for you. There is nothing to host, lock, back up or corrupt. That is a genuine operational saving and it is why AWS-native shops often stay put.

Terraform hands you the state file, which is both its greatest strength and its most common self-inflicted wound. You get to inspect it, move resources between configurations, import existing infrastructure and refactor deliberately. You also get to corrupt it if two engineers apply at once without locking. Use an S3 backend with locking, versioning and encryption from day one, on the first project, before it matters.

Side by side

DimensionTerraform / OpenTofuCloudFormation
ScopeMulti-cloud, thousands of providersAWS only, plus limited extensions
LanguageHCL — concise, readableJSON/YAML — verbose
StateYou own it (S3 plus locking)Managed by AWS
New AWS servicesProvider lag, usually days to weeksOften available at launch
Modules / ecosystemMassive public registrySmaller; StackSets, modules
Driftterraform planNative drift detection
Multi-accountProvider aliases, state per accountStackSets
Policy-as-codeOPA, Conftest, SentinelCloudFormation Guard
LicenceBUSL (Terraform) / MPL (OpenTofu)AWS service, no licence question

The licence question you now have to answer

HashiCorp relicensed Terraform from the Mozilla Public Licence to the Business Source Licence in 2023. OpenTofu is the community fork that followed and now sits under the Linux Foundation. For the overwhelming majority of infrastructure the two remain drop-in compatible.

For most teams building their own infrastructure the BUSL changes nothing in practice. It matters if you embed Terraform in a product, if you are a managed service provider, or if your legal team simply prefers a permissive licence. Ask the question deliberately once, record the answer, and move on — it is not worth relitigating every quarter.

Provider lag versus day-one coverage

CloudFormation frequently supports a new AWS service the day it is announced. Terraform’s AWS provider usually follows within days or weeks. If your business depends on adopting services at launch, that is a real argument for CloudFormation, or for a hybrid where a small CloudFormation stack covers the bleeding edge and Terraform runs everything else.

For most teams this is theoretical. You are far more likely to be provisioning VPCs, EKS clusters, RDS instances and IAM than something announced last week.

Where teams get it wrong

  • Running Terraform without remote state and locking — a reliable path to corrupted state and race conditions.
  • Treating CloudFormation YAML as inherently simple, until a 2,000-line template becomes unmaintainable without nested stacks.
  • Skipping policy-as-code, so an over-permissive IAM policy reaches apply because a reviewer was tired.
  • Writing one enormous root module instead of composable ones, then discovering every change plans the entire estate.
  • Importing everything at once during a migration rather than stack by stack.

Migrating from CloudFormation to Terraform

This is a common request and it is very doable, provided you do it incrementally. Terraform’s import blocks let you declare what you are adopting rather than running import commands one resource at a time, which makes the process reviewable.

The rule I hold to: migrate one stack at a time, and do not delete the CloudFormation stack until terraform plan for that scope is genuinely empty. An empty plan is the only honest proof that Terraform’s model matches reality. Anything else is optimism.

IaC is a compliance control, not just automation

Auditors increasingly ask how infrastructure changes are reviewed and approved. Infrastructure-as-code answers that directly — every change is a pull request with an author, a reviewer and a timestamp — provided nobody is making changes in the console alongside it.

That last clause is where teams actually fail. Console drift undermines the control even when the tooling is perfect. Drift detection is what makes the claim defensible, which is why I treat it as a compliance requirement rather than an operational nicety. More on the mapping in AWS compliance controls mapping.

My take after sixteen years

For most teams I default to Terraform — the module ecosystem and portability outweigh the provider lag, and OpenTofu keeps a genuinely open option available. I reach for CloudFormation when a client is deeply AWS-native, wants AWS-managed state, needs a service the day it launches, or needs StackSets for an organisation-wide baseline.

Either way, the wins come from modular structure, remote state discipline and security guardrails in the pipeline — not from the tool. I have never seen a project fail because it picked the wrong one. I have seen several struggle because state was on a laptop. Related: secure cloud landing zone and EKS vs ECS.

Common questions

Is Terraform better than CloudFormation?

For most teams, yes, mainly because of the module ecosystem and multi-cloud portability. CloudFormation still wins when you are entirely AWS-native, want AWS to manage state for you, or need a brand-new service on the day it launches. The gap is narrower than Terraform advocates usually admit.

Should I use OpenTofu instead of Terraform?

It is a real option. HashiCorp relicensed Terraform under the Business Source License in 2023, and OpenTofu is the open-source fork that followed, now under the Linux Foundation. For most infrastructure the two are drop-in compatible. Choose OpenTofu if licence terms matter to your organisation or your legal team asks; choose Terraform if you want HashiCorp's commercial ecosystem.

Can I migrate from CloudFormation to Terraform?

Yes, and it is less painful than it used to be. Terraform's import blocks let you bring existing resources under management declaratively rather than one CLI call at a time. Migrate stack by stack, never big-bang, and keep the CloudFormation stack in place until the Terraform plan for that scope is genuinely empty.

Do I really need remote state and locking?

Yes, from the second person onwards. Local state means two engineers can apply simultaneously and corrupt it, and it means your infrastructure's source of truth lives on someone's laptop. Use an S3 backend with locking, versioning and encryption enabled. Recovering a corrupted state file is far more expensive than setting this up correctly on day one.

Which is better for multi-account AWS setups?

CloudFormation StackSets are genuinely good at pushing a baseline across many accounts, and they are AWS-native. Terraform handles multi-account well too, through provider aliases and separate state per account, but you assemble it yourself. If your only requirement is an organisation-wide guardrail baseline, StackSets are hard to beat.

How do I stop unsafe infrastructure reaching apply?

Policy-as-code in the pipeline, not review discipline. Run OPA or Conftest against the Terraform plan, or CloudFormation Guard against the template, and fail the build. Reviewers miss an over-permissive IAM policy or a public S3 bucket eventually; a policy check does not get tired.

Need Terraform done right?

Modular IaC, remote state, policy-as-code and clean migrations on AWS.

Terraform consulting →Book a free call

Also relevant: Secure cloud landing zone · Terraform + EKS + CI/CD