Bicep vs. Terraform: I've Shipped Both
Ask "Bicep or Terraform?" in the wrong channel and you'll start a holy war.
I'd like to skip the war. I've written infrastructure-as-code in both, run both in production, and used both to take environment provisioning from days down to under an hour. They both solve the same core problem: declarative, version-controlled infrastructure.
But I'm not going to pretend I'm neutral, because I'm not. If your world is Azure, I think the right answer is clearer than the internet makes it sound. So here's the honest version: what each is good at, where I land, and why the state file matters more than almost anyone admits.
The Same Job, Two Accents
At the surface they rhyme. Here's a storage account in each.
Bicep:
resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: 'st${uniqueString(resourceGroup().id)}'
location: resourceGroup().location
sku: { name: 'Standard_LRS' }
kind: 'StorageV2'
properties: {
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
}
}Terraform:
resource "azurerm_storage_account" "this" {
name = "st${random_string.suffix.result}"
resource_group_name = azurerm_resource_group.this.name
location = azurerm_resource_group.this.location
account_tier = "Standard"
account_replication_type = "LRS"
min_tls_version = "TLS1_2"
allow_nested_items_to_be_public = false
}Same intent, different accent. If you can read one, you can read the other by the end of the afternoon. The real difference isn't the syntax. It's what happens underneath after you hit deploy.
Where Bicep Wins
If your world is Azure, Bicep has real, specific advantages.
- No state file to manage. Bicep deploys through Azure Resource Manager, and Azure itself is the record of what exists. There's no separate state file to store, secure, lock, or accidentally corrupt.
- New Azure features on day one. Because it's Microsoft's own language for Azure, new services and settings tend to work the moment they ship, instead of waiting on a third-party provider to catch up.
- First-class tooling. What-if previews, native pipeline tasks, and tight integration that just works when you're all-in on the platform.
- It's typed ARM without the pain. All the power of ARM templates, none of the thousand-line JSON by hand.
For a team that lives in Azure, Bicep takes work off your plate that Terraform asks you to take on.
Where Terraform Actually Earns It
I'm not here to bury Terraform. It's excellent, and there's a clear case where it's the right call: when you genuinely run more than one cloud.
- One language across many providers. Azure, AWS, GCP, Cloudflare, GitHub, and hundreds more, all in the same workflow. If you really operate in several of those, that consistency is worth a lot.
- A huge ecosystem. The module registry and years of community patterns mean you're rarely the first person to solve a given problem.
- Skills that travel. A Terraform engineer can move between clouds without relearning the whole approach.
That's a real strength, and I'd reach for Terraform without hesitating in a true multi-cloud shop. The key word is genuinely. "We might use another cloud someday" is not the same as running one today — and that difference is where most teams talk themselves into a cost they didn't need to pay.
The State File Is the Whole Conversation
Here's the part the tool comparison usually rushes past, and it's the part I care about most.
Terraform keeps a state file — its own separate record of what it believes exists. That file is powerful. It's also a permanent job. You have to store it somewhere safe, lock it so two people don't run changes at once, keep it from drifting away from reality, protect it because it can hold secrets, and untangle it on the bad day it gets out of sync. None of that is hard on day one. All of it is a tax you pay forever.
Bicep doesn't have a state file at all. It asks Azure what exists and works from that. You get the same declarative model — describe what you want, let the tool make it so — without ever owning that extra record.
And this is the part people get backwards: the state-file tax doesn't get smaller when you're small, and it doesn't become necessary when you're big. A side project with ten resources still has to babysit state in Terraform. A platform with thousands of resources in Azure does not suddenly need state to stay in control — I've run infrastructure at that size on a stateless, declarative model, and "thousands of resources" was never the thing that made state worth it. Scale doesn't justify the state file. Running multiple clouds does.
So if you're Azure-only, Bicep gives you everything you actually wanted from infrastructure as code — repeatable, reviewed, version-controlled environments — and quietly hands back the entire category of state-management headaches. That's not a small win. That's the win.
How I'd Actually Choose
Stripped of the religion, here's my call:
If you're all-in on Azure, use Bicep. It's the clear, obvious choice, and the no-state-file simplicity alone is worth it. Only reach for Terraform when you genuinely operate more than one cloud — and even then, think hard about whether your Azure footprint really needs to be dragged into a state-managed tool just to match the rest.
A few more things I hold to:
- Don't run two IaC tools for the same resources. Pick one per area and commit. Two tools fighting over the same infrastructure is its own outage waiting to happen.
- Match the tool to the team you have. The best tool your team can't confidently operate is worse than the good-enough tool they can.
- Don't take on state for a "someday." If multi-cloud is a maybe on a roadmap, it is not a reason to pay the state tax now. You can always add Terraform for the cloud you actually adopt, when you actually adopt it.
The Thing That Matters More Than the Tool
Here's what the holy war misses completely.
The reason my infrastructure took provisioning from days to under an hour wasn't Bicep, and it wasn't Terraform. It was the discipline around the tool. A small set of reusable modules instead of copy-pasted templates. Every infrastructure change reviewed like real code. A pipeline that showed exactly what was about to change before it changed anything. Once that was in place, standing up a new environment was a config file and a pipeline run — not a week of careful clicking and crossed fingers.
A messy Terraform setup and a messy Bicep setup fail the same ways: drift, hand-built environments nobody can reproduce, and one server everyone's afraid to touch. A disciplined setup succeeds in either one.
The Takeaway
Bicep or Terraform is a real decision, but a smaller one than the arguments suggest — and for most teams I think it's clearer than the debate lets on. If you live in Azure, use Bicep, skip the state file, and don't look back. If you truly run more than one cloud, Terraform earns its keep. Either one, run with real discipline, will serve you for years.
So pick based on how many clouds you actually run, not the ones you might. Then spend your real energy on modules, reviews, and a deploy you can trust. That's where days-to-minutes comes from — not the file extension.


Comments (0)
No comments yet. Be the first to share your thoughts!
Leave a Comment
Sign in with Google, Microsoft, or email to leave a comment.