This argument usually gets decided by whoever spoke first in the meeting, which is a shame because the trade-offs are real and easy to state.
Where Bicep is genuinely better
No state file. Bicep deploys against Azure Resource Manager, which is itself the source of truth. There is no state to store, lock, corrupt or drift from reality. A large fraction of the operational work of running Terraform — backends, locking, state surgery after a failed apply, import for resources created by hand — simply does not exist.
Day-one resource support. A new Azure feature is available in Bicep as soon as the ARM API supports it, because Bicep is a thin typed layer over the API. The Terraform provider follows behind, sometimes by months. If you adopt Azure features early, this matters and you will notice it.
What-if is accurate at the API level. az deployment what-if asks Azure what would change, rather than comparing to a state file that may not match reality.
Deployment stacks give you a managed lifecycle for a set of resources, including deny-settings that stop out-of-band changes — a capability with no direct Terraform equivalent.
Where Terraform is genuinely better
It is not only Azure. Almost every real estate has something else: a DNS provider, GitHub, Cloudflare, Datadog, a database schema, another cloud. One tool and one workflow across all of it is a large practical advantage, and it is the argument that wins most often.
The module and community ecosystem is far larger. For most patterns, someone has published a reviewed module.
Explicit, readable plans as a review artefact. The terraform plan output posted on a pull request is something a reviewer can reason about, and the workflow around it — plan, approve, apply the saved plan — is well established.
A stronger testing and policy story. checkov, tfsec, conftest, Terratest and the policy-as-code ecosystem are mature. Bicep has linting and the ARM template test toolkit, but the tooling is thinner.
Drift detection. A terraform plan on a schedule tells you what changed outside the pipeline. Bicep's model, where ARM is the truth, means out-of-band changes are simply reality until the next deployment overwrites them — unless you use deployment stacks with deny settings.
How to choose
Azure-only, Microsoft-centric team, a platform team that lives in Azure DevOps: Bicep. The absence of state is a real operational saving and the day-one support is a real capability. Use deployment stacks and deny settings to get drift protection back.
Multi-cloud, or significant non-Azure infrastructure, or a team that already knows Terraform: Terraform. The cost of a second tool and a second mental model exceeds Bicep's advantages.
Large organisation with both: pick one per boundary rather than mixing inside a layer. Bicep for the application deployments that a product team owns, Terraform for the platform and landing zone. What does not work is two tools managing the same resource group — the last one to run wins and neither knows it.
If you choose Terraform, the Azure-specific things to get right
features {}is required in the provider block and its defaults are opinionated, particularly for Key Vault soft-delete and purge.- Authenticate CI with OIDC federated credentials on a user-assigned managed identity, never a client secret.
- Resource locks applied by policy will make
terraform destroyfail in staging, confusingly, the first time. - State in a storage account in the management subscription, with versioning and a lock on the container.
- One state per subscription per layer, the same structure as we use on AWS.
If you choose Bicep
- Use deployment stacks for anything you want protected from out-of-band change.
- Run
what-ifin the pull request and post the output, the same discipline as a Terraform plan. - Keep modules in a private Bicep registry in an Azure Container Registry, versioned, rather than in relative paths across repositories.
- Azure Policy is still your governance layer, not the deployment tool — see policy as code. This is true whichever tool you pick, and it is the more important decision of the two.
Either way, the deployment tool matters less than the structure it deploys: the management groups, the subscription boundaries and the policies in the landing zone piece. We have delivered both, and the projects that went well were not distinguished by this choice.
What to do this week
Count the non-Azure things in your infrastructure that are currently managed by hand — DNS records, GitHub repository settings, monitoring configuration. If that list is long, it is the argument for Terraform. If it is empty, Bicep will cost you less to operate.