Platform Engineering
Terraform, Bicep, CloudFormation or CDK
How to choose an infrastructure as code tool based on your cloud estate, team skills and operating model, rather than on which one has the better syntax.
- Author
- Celestique Cloud
- Published
- Reading time
- 7 min read
The infrastructure as code question gets argued on the wrong axis. Teams debate syntax, and syntax is the thing you stop noticing after a fortnight.
The decision that matters is about state, blast radius and who has to operate it at 3am. Here is how the four options actually differ on that.
The single most important distinction
Terraform maintains its own state file. The others do not.
Bicep and CloudFormation both delegate state to the cloud provider. Azure Resource Manager and CloudFormation know what exists because they created it, and they reconcile against live resources. CDK is not a separate answer here: it synthesises CloudFormation templates, so it inherits CloudFormation's model entirely.
This has consequences that show up on a bad day rather than in a tutorial.
Terraform's state is an asset you own and must protect. It needs remote storage, locking so two pipelines cannot corrupt it, encryption, backup, and a recovery procedure someone has actually rehearsed. In exchange, you get a genuine plan step that tells you what will change before it changes, and you get one tool across every provider you use.
Provider-native state cannot be corrupted by you, and cannot be fixed by you either. There is no state file to lose. There is also no state file to repair when a deployment fails in a way the provider did not anticipate. A CloudFormation stack in UPDATE_ROLLBACK_FAILED is a specific kind of afternoon.
Neither is better. They fail differently, and you should choose the failure mode your team is equipped to handle.
Where each one is the obvious choice
Bicep
Choose it when your estate is Azure and expected to stay Azure.
Bicep is a transparent abstraction over ARM. Its decisive advantage is timing: because it compiles to ARM, new Azure resource types and properties are available as soon as the provider ships them, with no waiting for a third party to model them. On a fast-moving service, that gap is real.
The tooling is good. what-if gives you a preview of changes, deployment stacks manage resource lifecycle as a unit, and Azure Verified Modules provide a maintained module library rather than leaving you to assemble one.
The limitation is exactly what you would expect: it is Azure only. If you have anything else under management, and most organisations do, you are running a second tool alongside it.
CloudFormation
Choose it when your estate is AWS, and you want the smallest possible dependency footprint.
It is the native service, it is free, it needs nothing installed, and change sets give you a preview before applying. Stack policies protect resources from accidental replacement. It is boring in the way infrastructure tooling should be.
Two honest drawbacks. Raw YAML or JSON templates get verbose quickly, and the loops and conditionals are awkward compared to a real language. And when a stack update fails badly, recovery can require operations that feel disproportionate to the change you were making.
CDK
Choose it when the people writing infrastructure are software engineers and the estate is AWS.
CDK lets you define infrastructure in TypeScript, Python, Java, Go or C#. You get types, loops, functions, unit tests and your existing editor tooling. Its constructs encode sensible defaults, so a small amount of code produces a well-configured resource set.
The trade-off is a layer of indirection. You are not writing the thing that gets deployed, you are writing a program that generates it. When something is wrong, you sometimes debug the generated CloudFormation rather than your code, and you need to be comfortable doing that. Abstraction that nobody on the team can see through becomes a liability during an incident.
There is also a discipline question. Because it is a general-purpose language, it is possible to write genuinely clever infrastructure code. Resist. Infrastructure code is read under pressure by someone who did not write it.
Terraform
Choose it when you are multi-cloud, when you manage significant infrastructure outside your primary cloud, or when you want one workflow across everything.
This is the practical case and it is more common than "multi-cloud" makes it sound. An organisation entirely on Azure for compute still often has DNS at Cloudflare, identity in Okta, monitoring in Datadog, repositories on GitHub and a SaaS platform with a management API. Terraform manages all of it with the same plan-and-apply loop. That consistency is the actual product.
The costs are real and you should price them in: you own the state, the provider for a given service can lag the service itself, and you carry a tool dependency and its licensing.
Two questions that decide it faster than a feature matrix
How many clouds and platforms will this team manage in three years?
One, and it is Azure, and you are confident: Bicep. One, and it is AWS: CloudFormation, or CDK if your team is engineers rather than operators. More than one, or a meaningful amount of non-cloud infrastructure: Terraform.
Who is on call for this at 3am, and what can they read?
If the on-call engineer is an infrastructure specialist who is comfortable with declarative templates, native tooling is fine. If they are a software engineer, CDK's familiarity is worth something real. If they are neither, whatever you choose needs to be written plainly and documented, and that matters more than the choice.
Things that matter more than the tool
Whichever you pick, these determine whether it works:
Modules and reuse. Every environment defined by copy-paste guarantees drift. Both major clouds now publish maintained module libraries; use them before writing your own.
A pipeline, not a laptop. Infrastructure applied from an engineer's machine is infrastructure with no audit trail and one point of failure. Plan on pull request, apply on merge, with the credentials held by the pipeline and not by a person.
Least-privilege deployment identity. The pipeline identity is often the most privileged thing in the environment and the least reviewed. Scope it, rotate it, and audit what it did.
No secrets in code or state. Reference a secret store. Note specifically that Terraform state can contain sensitive values in plain text, which is a common and avoidable exposure.
Drift detection. Something will get changed in a console during an incident. You want to find out on a schedule, not during the next deployment.
Test the destroy path. Plenty of teams have working create paths and have never verified that teardown works cleanly. You find out when you need to rebuild.
The pragmatic answer
Most organisations we work with land in one of three places:
- Azure only, infrastructure team: Bicep, with Azure Verified Modules and deployment stacks.
- AWS only, engineering team: CDK, with a rule that constructs stay readable and the synthesised output is reviewed.
- Anything more complicated than that: Terraform, with remote state, locking, and a documented recovery procedure.
And a genuinely defensible fourth position: keep what you already have. A working Bicep estate should not be converted to Terraform because a new engineer prefers it. Migration between IaC tools is expensive, risky, and delivers nothing a stakeholder can see. The best tool is usually the one your team already runs well.
If you want help deciding, or a review of an existing estate, that is what our platform engineering practice does.
Sources
Official vendor and standards-body documentation referenced while writing this article.
- 01Bicep documentationMicrosoft (opens in a new tab)
- 02Azure Verified ModulesMicrosoft (opens in a new tab)
- 03AWS CloudFormation User GuideAmazon Web Services (opens in a new tab)
- 04AWS Cloud Development Kit Developer GuideAmazon Web Services (opens in a new tab)
- 05Terraform documentationHashiCorp (opens in a new tab)
- 06Terraform state documentationHashiCorp (opens in a new tab)
Tags
- Infrastructure as code
- Terraform
- Bicep
- CloudFormation
- CDK
Related services
Platform Engineering and IaC
Repeatable delivery through pipelines and infrastructure as code.
Cloud Modernisation
Modernise ageing systems and establish a cloud operating model.
Keep reading
Cloud Modernisation
What a cloud migration assessment should include
7 min read
AI and Automation
How to identify an AI use case worth funding
7 min read
Free discovery workshop
Start with clarity, not commitment.
Bring one process or technology challenge. We will map the opportunity, the readiness gaps and a recommended next step.