Bicep vs. Terraform: I've Shipped Both
Ask "Bicep or Terraform?" in the wrong channel and you'll start a holy war I'd rather sit out. 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.
I've got a horse in this race, though. If your world is Azure, I think the right answer is a lot clearer than the internet makes it sound, and the biggest reason is the state file, which most comparisons treat as a footnote.
The Same Job, Two Accents
Side by side they look pretty similar. 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, which is why the syntax debate has never interested me much. The difference that matters is 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. Everything ARM templates can do, without writing the thousand-line JSON yourself.
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
Terraform is excellent, and there's a clear case where it's the right call: 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 in a true multi-cloud shop I'd reach for Terraform without hesitating. The key word is genuinely, though. "We might use another cloud someday" is not the same as running one today, and that gap is where a lot of teams talk themselves into a cost they didn't need to pay.
The State File Is the Whole Conversation
Terraform keeps a state file — its own separate record of what it believes exists in your environment. The file is powerful, and it's also a permanent job. You have to store it somewhere safe, lock it so two people can'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. It's a tax you keep paying for as long as the infrastructure exists.
Bicep has no state file at all. It asks Azure what exists and works from that, so you get the same declarative model (describe what you want, let the tool make it so) without ever owning that extra record.
The usual pushback is that state becomes necessary at scale, and my experience says otherwise. A side project with ten resources still has to babysit state in Terraform, and a platform with thousands of resources in Azure stays in control without it. I've run infrastructure at that size on a stateless, declarative model, and the resource count was never the thing that made state look worth it. What makes state worth it is running more than one cloud.
So if you're Azure-only, Bicep delivers the repeatable, reviewed, version-controlled environments you wanted from infrastructure as code in the first place, and the whole category of state-management headaches never shows up. That's the point I give the most weight in this comparison.
How I'd Choose
Where I land, after shipping both:
If you're all-in on Azure, use Bicep. It's the obvious choice, and skipping the state file is worth it on its own. 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. A good-enough tool your team can run with confidence beats a better one they can't.
- Don't take on state for a "someday." A maybe on the roadmap isn't 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
When my provisioning times fell from days to under an hour, the tool was the smallest part of it. Most of the credit belonged to the discipline around it: a small set of reusable modules instead of copy-pasted templates, every infrastructure change reviewed like real code, and 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 instead of 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 does fine in either one.
The Takeaway
Bicep or Terraform is a real decision, just a smaller one than the volume of the argument suggests. Count the clouds you actually run today and pick for that. Azure-only means Bicep, and don't look back. A genuine second cloud means Terraform earns its keep. Run either one with real discipline, modules and reviews and a deploy you can trust, and it'll serve you for years. The under-an-hour number came from that discipline a lot more than from the file extension.
If you're still stuck, scroll back up to the two snippets. They describe the same storage account. Only one of them comes with a state file to carry for the life of the project, and for an Azure-only team, that's pretty much the whole decision.


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.