The real question behind "terraform vs cloudformation" is rarely which tool is better in the abstract — it's which one fits your team, your cloud footprint, and the next two years of where you're headed. This is the neutral, practitioner-grade breakdown: multi-cloud vs AWS-native, the two very different state models, HCL vs YAML/JSON (and where CDK changes the math), the module ecosystems, who supports new AWS services first, how rollback actually behaves, StackSets vs Terraform workspaces for multi-account, and the BSL/OpenTofu licensing situation. Plus an honest verdict and a decision table — and how CloudRoute routes you to a vetted AWS partner who sets up either one correctly (often AWS-funded, so $0 if you qualify).
Both tools do the same core job: turn a written description of your AWS resources into reality and keep it that way. They differ in who owns the state, how many clouds they speak, what language you write, and how big the surrounding ecosystem is. Those four differences drive almost every other trade-off on this page.
Strip away the tribalism and the decision is mostly about footprint and fit. CloudFormation is Amazon's own infrastructure-as-code service: you hand AWS a template — YAML or JSON — describing the resources you want, AWS creates a "stack" from it, and AWS holds and reconciles the state on its side. It is free (you pay only for the resources it creates) and it is the substrate a lot of higher-level AWS tooling (SAM for serverless, much of the CDK, Service Catalog) is built on top of.
Terraform is HashiCorp's tool, and it is provider-based: AWS is just one of hundreds of providers it can drive, alongside Google Cloud, Azure, Cloudflare, Datadog, GitHub, Okta, Kubernetes, and your DNS registrar. You write HCL (HashiCorp Configuration Language), Terraform builds a dependency graph, shows you a plan, and applies it — and you own the state file that records what it created. Since 2023 Terraform has been under HashiCorp's Business Source License (BSL) rather than a traditional open-source license, which is why the community created OpenTofu, an MPL-licensed near-drop-in fork; for the rest of this page, "Terraform" means "Terraform or OpenTofu" unless the licensing distinction matters.
There is a third option that quietly resolves a lot of the language argument: the AWS Cloud Development Kit (CDK). CDK lets you write infrastructure in TypeScript, Python, Java, Go, or C#, then synthesizes a CloudFormation template under the hood and deploys it as a stack. So when people say "CloudFormation is verbose YAML," CDK is the standard answer — real programming-language abstraction while still landing on AWS-managed CloudFormation state. We treat CDK throughout as "CloudFormation with a better front-end," because mechanically that is exactly what it is. One honest meta-point before the factor-by-factor breakdown: this is one of the most over-debated decisions in infrastructure, and the stakes are lower than the internet implies — a well-run setup in either tool gives you repeatable, reviewable, auditable infrastructure, and a badly-run version of either gives you drift, fear, and 2am surprises.
Multi-cloud or ecosystem-heavy → Terraform/OpenTofu. AWS-only and you want AWS-managed state plus day-one new-service support → CloudFormation/CDK. Either, done with proper state, pipelines, and policy-as-code, is a good outcome — and the choice is reversible.
This is the single biggest discriminator, and for a lot of teams it settles the question on its own. CloudFormation is AWS, only AWS, deeply AWS. Terraform is AWS plus everything else, through one workflow.
CloudFormation can only manage AWS resources. That sounds limiting, and at the edges it is, but the upside is depth: because it is AWS's own service, it tends to model AWS resources faithfully and integrate with AWS-native concepts — stack policies, change sets, drift detection, nested stacks, Service Catalog, organization-wide deployment — without an intermediary. If your entire world is AWS and you value being inside Amazon's own tooling, that depth is a genuine asset.
Terraform's pitch is the opposite: one tool, one language, one workflow for your whole stack. The same plan/apply loop that creates your VPC and ECS service also configures your Cloudflare DNS and WAF, your Datadog monitors, your GitHub repos and branch protection, your Auth0/Okta tenant, your PagerDuty schedules, and your Kubernetes resources. For a modern startup whose "infrastructure" is rarely 100% AWS — there is almost always a CDN, an observability vendor, a DNS provider, an identity provider, some SaaS with an API — that single pane of glass is the headline reason Terraform became the industry default.
The practical test is simple: list everything you want under code in the next two years. If that list is essentially "AWS, and maybe a DNS record," CloudFormation/CDK is sufficient and you lose little; if it includes a second cloud or three or four SaaS platforms with mature Terraform providers, Terraform consolidates all of it into one review-and-apply workflow. And state the nuance honestly: "multi-cloud" as a buzzword is oversold — very few startups genuinely run active-active across AWS and GCP, and you should not pick a tool for a multi-cloud future you will never have — but "multi-provider" is almost universal, since even single-cloud teams manage Cloudflare, GitHub, Datadog, and a DNS registrar. That is where Terraform's breadth actually pays off, not in the imaginary case where you mirror your whole platform onto a second hyperscaler.
How each tool remembers what it created is the deepest architectural difference between them, and it shapes day-to-day operations more than anything else. CloudFormation keeps state for you, server-side. Terraform hands you a state file and the responsibility that comes with it.
With CloudFormation, there is no state file you own or can lose. AWS tracks the desired and actual state of every stack on its side, so you never think about a backend, never worry about two engineers corrupting a shared file, never run a manual unlock. Drift — when someone changes a resource by hand in the console so reality no longer matches the template — is caught by AWS's built-in drift detection, which reports per-resource differences against the stack. The trade-off is that you operate at the granularity of stacks: surgical changes to one resource's state are harder than in Terraform because you do not hold the state to edit.
With Terraform, the state file is a real artifact you must manage well. In any serious setup it lives in a remote backend — most commonly an S3 bucket with a lock (DynamoDB historically; S3-native conditional-write locking is now also supported) so two people can't apply at once and clobber each other. State maps your code to the real resource IDs plus the metadata Terraform needs to compute diffs. Done right, this is a non-issue and gives you power: terraform state mv to refactor without destroying, terraform import to bring existing resources under management, and surgical removal of a single resource from state. Done wrong — state on a laptop, no locking, no backups — it is the classic Terraform footgun, and the single most common reason a DIY setup turns scary.
Both tools surface drift, differently. CloudFormation has explicit drift detection you run against a stack; it reports which properties of which resources no longer match the template, but it does not auto-correct — you reconcile by updating the stack. Terraform surfaces drift every time you run terraform plan: it refreshes real-world state, diffs it against your code, and shows exactly what it would change to bring reality back in line — which many teams run on a schedule in CI as a continuous drift check. In both cases the right answer is cultural, not technical: lock down console write access so humans stop hand-editing managed resources, and make code the only path to change. The tool barely matters if half the team is still clicking around in the console behind its back.
How you actually write the infrastructure is the factor people argue about loudest. It is also the one where CDK quietly defuses the strongest criticism of CloudFormation.
Terraform uses HCL, a purpose-built configuration language. It is declarative but has just enough programmability — variables, locals, for_each and count loops, conditionals, functions, and module composition — to express real abstractions without turning into a general-purpose program. Most engineers find HCL readable within a day and pleasant within a week; it hits a deliberate sweet spot between "dumb config" and "full programming language."
Raw CloudFormation is YAML or JSON, and this is where its reputation suffers. Plain CloudFormation templates get verbose fast, and expressing anything dynamic — loops, conditionals, computed values — through intrinsic functions like !Ref, !GetAtt, !Sub, Fn::If, and Fn::ForEach is clunky compared to HCL. A large hand-written YAML template is not a fun thing to read or maintain, and "the YAML gets unwieldy" is the single most common, and most fair, complaint about CloudFormation.
Then comes CDK, which reframes the whole argument. With CDK you write infrastructure in a real language — TypeScript, Python, Java, Go, or C# — with loops, classes, types, IDE autocomplete, unit tests, and your own reusable constructs, and CDK synthesizes the CloudFormation template for you. For teams who want programmatic power and already live in TypeScript or Python, CDK is frequently more ergonomic than HCL, not less — the full expressiveness of a programming language on top of AWS-managed state. The catch is the flip side of that power: it is easy to write CDK that is too clever, abstractions can hide what is actually being deployed, and you still ultimately debug a generated CloudFormation template when something breaks. (Terraform has an equivalent, CDKTF, but it sees far less adoption than CDK does on AWS.)
Net: compared to raw YAML, HCL wins comfortably on ergonomics; compared to CDK, it is a real contest that comes down to whether your team would rather learn a focused config language or stay in a programming language they already know. Neither answer is wrong.
Most "CloudFormation is awful to write" takes are really "raw YAML is awful to write" — which is true. The fair modern comparison is HCL vs CDK, and that one is genuinely close. If you are AWS-only and your team loves TypeScript, CDK's ergonomics are a legitimate reason to stay AWS-native.
You should not be hand-writing a production VPC, an EKS cluster, or an RDS instance with all its best-practice settings from scratch. How much pre-built, battle-tested infrastructure you can pull off the shelf differs sharply between the two.
Terraform's ecosystem is its quiet superpower. The public Terraform Registry hosts thousands of community and vendor modules, and the canonical terraform-aws-modules collection (the AWS VPC, EKS, RDS, ALB, IAM, and security-group modules) is so widely used that it is effectively a standard — these modules encode years of accumulated best practice, are maintained by people who do this full-time, and let a small team stand up a sensible VPC or EKS cluster in a few dozen lines instead of a few hundred. Private module registries (Terraform Cloud, or internal Git-based modules) let you publish your org's own opinionated building blocks for teams to reuse. This depth of reusable, community-vetted infrastructure is, for many teams, the most concrete reason to choose Terraform.
CloudFormation's reuse story is real but thinner. You compose with nested stacks and StackSets, and AWS provides quick-start templates and Service Catalog products, but there is no single bustling public registry of community modules on the scale of Terraform's. CDK improves this meaningfully through Constructs — its L2 and L3 constructs encode AWS best practices in code (a single high-level construct can stand up a well-configured Fargate service behind a load balancer), and Construct Hub aggregates shareable construct libraries. So CDK narrows the gap considerably for AWS-native resources. But for the long tail — and especially for non-AWS providers — Terraform's registry is in a different league, and that gap widens the moment your infrastructure includes anything outside AWS.
The hiring-and-knowledge dimension rides alongside this. Because Terraform is the broad-market default, the pool of engineers who already know it, the volume of community answers and blog posts, and the supply of consultants who can drop in and be productive are all larger. CloudFormation and CDK have strong, AWS-backed docs and a solid community, but the ambient cross-company familiarity is greater for Terraform — which matters when you are hiring or bringing in outside help.
Two AWS-native advantages for CloudFormation deserve their own section, because they are the strongest arguments on its side of the table: how fast new AWS features become usable, and what happens when a deployment fails.
When AWS launches a new service or a new property on an existing one, CloudFormation tends to support it at or very near launch — it is AWS's own tool, shipped by the same company, so coverage of the newest AWS surface area is usually first and most complete (CDK inherits this, since it synthesizes to CloudFormation). With Terraform, that same capability has to land in the AWS provider, which is maintained as a separate project; the AWS provider is large, fast-moving, and very well maintained, so the lag is often days to a few weeks rather than months — but a lag exists, and if you are the kind of team that adopts brand-new AWS services the week they ship, CloudFormation/CDK genuinely serves you better. (When the provider does lag, Terraform's aws_cloudcontrolapi_resource and escape hatches can bridge the gap, but it is friction.)
Rollback is the other native edge. When a CloudFormation stack update fails partway through, CloudFormation automatically rolls the stack back to its last known-good state by default — a real safety net that means a botched change tends to leave you where you started rather than half-applied. Terraform has no equivalent automatic rollback: if an apply fails midway, it stops, and you are left with a partially-applied change plus a state file that reflects what did and did not happen; you fix forward (correct the code and re-apply) rather than relying on an automatic revert. Experienced Terraform teams manage this fine with small, frequently-applied changes and good CI gating, but CloudFormation's built-in rollback is a legitimate point in its favor, especially for less experienced operators.
Keep these advantages in proportion, though. Same-day new-service support matters enormously to a minority of teams and almost not at all to the majority, who adopt new AWS services months after launch if ever; and automatic rollback is no substitute for the discipline that prevents bad applies in the first place. These are real CloudFormation strengths — decisive only for specific teams.
Same-day support for the newest AWS services, automatic stack rollback on failed updates, and zero state to operate. If "be on the bleeding edge of AWS with the most safety rails and the least operational overhead" describes your priorities, that is the strongest honest case for CloudFormation/CDK — and it is a good one.
Any company that is serious about AWS ends up with many accounts (prod, staging, dev, security, logging, sandbox) across multiple regions. How each tool fans a configuration out across that estate differs in mechanism and in feel.
CloudFormation's built-in answer is StackSets: define a template once and have AWS deploy and maintain it as stack instances across many accounts and regions, with native hooks into AWS Organizations so new accounts can be enrolled automatically. Because StackSets is an AWS-managed orchestration layer, it handles the cross-account deployment plumbing for you — which is a clean fit when your multi-account structure is itself built on AWS Organizations and Control Tower, and you want AWS to own the fan-out.
Terraform approaches the same problem differently, and here the terminology trips people up. Terraform workspaces are often misunderstood as the multi-account/multi-environment mechanism, but native CLI workspaces really just let one configuration keep multiple state files; most experienced teams deliberately do not use them to separate prod from staging. The mainstream Terraform pattern is instead separate state per account/environment — distinct directories or repositories, each with its own backend and its own provider configuration assuming a role into the target account — often orchestrated with a tool like Terragrunt (or Terraform Cloud/Enterprise workspaces, which are a different, more powerful concept than CLI workspaces) to stay DRY across them. The result is the same outcome as StackSets — one source of truth applied across many accounts — but you assemble the pattern rather than getting it as a single managed feature.
The trade-off mirrors the state discussion. StackSets gives you a managed, AWS-native fan-out — less to build, but less flexibility and an AWS-only ceiling. The Terraform per-environment pattern is more assembly up front, but it is more flexible, it spans non-AWS providers in the same breath, and it is the model the broad market has the most operational experience running. Either way, this multi-account wiring is precisely the kind of foundation a vetted partner sets up correctly so you inherit a clean structure instead of growing one by accident.
The licensing landscape changed in 2023 and is now a settled but real consideration. CloudFormation has no licensing question at all; Terraform has one, and OpenTofu is the answer most teams reach for.
On the AWS-native side, licensing is simply not a factor: CloudFormation is a free AWS service with no license to weigh and no cost beyond the resources it creates, and CDK is open-source (Apache 2.0). The question only exists on the Terraform side. In August 2023, HashiCorp relicensed Terraform from the open-source Mozilla Public License to the Business Source License (BSL) 1.1. For the vast majority of users this changes nothing — you can still freely use Terraform to manage your own infrastructure, commercially, at any scale. The BSL's restriction is narrow and aimed at vendors: it forbids offering Terraform itself as a competing commercial product or service. If you are an ordinary company using Terraform to run your own AWS, the BSL does not constrain you in practice.
The relicensing nonetheless prompted the community, under the Linux Foundation, to fork the last MPL-licensed version into OpenTofu — a fully open-source (MPL 2.0), drop-in-compatible alternative that reads the same HCL, uses the same providers and modules, and runs the same plan/apply workflow. By 2026 OpenTofu is mature, actively developed, and a common default for teams that want a guaranteed-open foundation, and migrating an existing Terraform codebase to it is typically low-effort. So the modern choice is really three-way — CloudFormation/CDK, Terraform under BSL, or OpenTofu under MPL — and "use OpenTofu, keep everything else the same" is a perfectly reasonable way to get Terraform's ecosystem without the BSL question hanging over it.
Using Terraform to run your own infrastructure is unaffected by the BSL — the restriction targets vendors reselling Terraform, not you. If the license still gives you pause, OpenTofu is the open (MPL 2.0) drop-in: same HCL, same providers, same modules. CloudFormation/CDK sidesteps the question entirely.
Neutral does not mean wishy-washy. Here is the straight call on which tool fits which situation — stated plainly enough to act on. Reach for <strong>CloudFormation / CDK</strong> when these describe you:
Reach for Terraform / OpenTofu instead when you run (or will run) more than one cloud; when your infrastructure includes a lot of non-AWS SaaS (Cloudflare, Datadog, GitHub, Okta/Auth0, PagerDuty, your DNS registrar) — the near-universal real-world case even for "single-cloud" shops; when you want the module ecosystem and the hiring pool (the Registry and the canonical terraform-aws-modules collection let you stand up best-practice infrastructure fast, and broad familiarity means more engineers and consultants are productive immediately); when you want surgical control over state (state mv, import, targeted removes, refactors without destroy/recreate); or when you want to avoid lock-in on the IaC layer itself, keeping definitions portable across providers, with OpenTofu keeping that layer guaranteed-open.
In one sentence: the wider and more heterogeneous your infrastructure, the more Terraform/OpenTofu pulls ahead; the more it is pure AWS and the more you value native integration and managed state, the more CloudFormation/CDK holds its own. The broad market has tilted toward Terraform/OpenTofu as the default — but "AWS-native shop runs CloudFormation/CDK well" remains a completely legitimate, defensible choice, not a thing to apologize for.
The factors that actually drive the choice, scored honestly. "CDK" notes show where authoring CloudFormation in a real language changes the answer. Neither column is a wrong choice — this is about fit.
| Factor | Terraform / OpenTofu | CloudFormation / CDK |
|---|---|---|
| Cloud scope | Multi-cloud + hundreds of providers (AWS, GCP, Azure, SaaS) | AWS only — but deep, native AWS integration |
| State model | You operate it: remote state (S3 + locking), backups, scalpel-level control | AWS-managed stacks — no state file to lose or corrupt |
| Drift | Surfaced on every plan; easy to run as a scheduled CI check | Explicit drift detection per stack (manual reconcile) |
| Language | HCL — focused, readable, lightly programmable | YAML/JSON (verbose) → CDK gives TypeScript/Python/etc. |
| Module ecosystem | Huge: Terraform Registry + terraform-aws-modules standard | Thinner: nested stacks/StackSets; CDK Constructs narrow the gap |
| New AWS service support | Days-to-weeks lag via the AWS provider | At/near launch — AWS's own tool ships day one |
| Rollback on failed deploy | No auto-rollback — stop and fix forward | Automatic stack rollback to last good state (default) |
| Multi-account fan-out | Per-env state + Terragrunt/TFC workspaces (assembled) | StackSets — managed, native, Organizations-aware |
| Licensing | Terraform = BSL (fine for self-use); OpenTofu = MPL open | Free AWS service; CDK is Apache 2.0 — no license question |
| Hiring pool / market share | Broad-market default — largest talent + content pool | Strong AWS-native community; smaller cross-company familiarity |
| Best fit | Multi-cloud, SaaS-heavy, ecosystem-driven teams | AWS-only teams wanting native depth + managed state |
Situation: The team had stalled on "Terraform vs CloudFormation" for two months and shipped nothing — every infra change was still a console click, staging and prod had quietly drifted apart, and an upcoming SOC 2 effort needed an audit trail they did not have. They genuinely could not tell whether being AWS-only meant they "should" use CloudFormation, and nobody in-house had run either at production scale.
What CloudRoute did: CloudRoute routed them within ~20 hours to a UK-based AWS partner with both Terraform and CDK in production. On a 45-minute scoping call the partner mapped their two-year footprint: AWS plus Cloudflare, Datadog, and GitHub already in the mix — so Terraform/OpenTofu was the clear fit, and the partner recommended OpenTofu to sidestep the BSL question entirely. They then imported the existing hand-built account under OpenTofu (no destroy/recreate), stood up S3-backed locked remote state, a plan/apply pipeline with an approval gate, tflint + checkov scanning, and a clean prod/staging/sandbox account split.
Outcome: Production-grade IaC foundation delivered in just under 4 weeks; staging and prod reconciled and re-creatable from code; Git history now serves as the SOC 2 change log. Because the company was credit-eligible, the engagement was AWS-funded and the customer paid $0. The two-month tool debate was settled in one call by someone who runs both — and the decision was framed as reversible, which is what finally let them move.
engagement window: ~4 weeks · founder time: ~6 hours · tool chosen: OpenTofu (Terraform-compatible) · cost to customer: $0 (credit-eligible)
CloudRoute routes you to a vetted AWS partner who runs both Terraform/OpenTofu and CloudFormation/CDK, gives you a straight recommendation for your footprint, and builds the whole foundation. For credit-eligible companies it's often AWS-funded — $0 to you. No procurement, no discovery theater.