Bicep and infrastructure as code on Azure
Azure has three IaC options and the interview question is which you would pick. The short answer: Bicep for Azure-only, Terraform when the estate is not.
What Bicep is
Bicep is a domain-specific language that compiles to ARM templates. ARM is Azure’s native deployment format - JSON, verbose, and unpleasant to write by hand. Bicep is the same model with a readable syntax.
param location string = resourceGroup().location
resource plan 'Microsoft.Web/serverfarms@2023-01-01' = {
name: 'api-plan'
location: location
sku: { name: 'P1v3' }
}
resource site 'Microsoft.Web/sites@2023-01-01' = {
name: 'api-prod'
location: location
properties: { serverFarmId: plan.id }
}Two things follow from compiling to ARM rather than being its own engine:
- No state file. Azure Resource Manager already knows what exists, so Bicep asks it rather than keeping a record. This removes Terraform’s whole class of state problems - locking, drift between state and reality, secrets sitting in plaintext in the state file.
- Same-day resource support. Because it targets ARM directly, a new Azure resource is usable immediately, rather than waiting for a provider release.
Referencing plan.id creates an implicit dependency, so ordering is derived
rather than declared - the same idea as Terraform’s graph.
Bicep versus Terraform
| Bicep | Terraform | |
|---|---|---|
| Scope | Azure only | Multi-cloud |
| State | None; ARM is the record | State file to manage |
| New services | Immediate | Waits for the provider |
The decision is rarely about the languages. It is about the estate. A team already running Terraform for AWS or Cloudflare should not adopt a second tool and a second set of habits for the Azure slice. A team wholly on Azure gets a simpler operational story with Bicep, mostly by not having state to look after.
The third option, ARM templates directly, is legacy. Write Bicep and let it compile; you can always inspect the ARM output.
What-if, the equivalent of plan
The reviewable diff before applying:
az deployment group what-if \
--resource-group prod \
--template-file main.bicepRun it in the pipeline on a merge request so a human sees the change before it
happens. This is the same discipline as terraform plan in CI, and it is the
control that makes infrastructure changes reviewable - see
CloudFormation vs Terraform.
what-if is less precise than terraform plan: it sometimes reports
properties as changing when they will not, because it compares against the
resource’s full declared shape. Treat noisy lines as noise, but never treat a
deletion as noise.
Deployment modes
The setting that causes accidents. Incremental (the default) leaves resources not mentioned in the template alone. Complete deletes anything in the resource group that the template does not declare.
Complete mode makes the template genuinely authoritative, which is what you
want for a managed environment - and it will delete a resource someone created
by hand in the portal. That is the point, and it is also why you run what-if
first.
Modules
Bicep modules are files you invoke with parameters, the same composition idea as a Terraform module:
module api 'modules/webapp.bicep' = {
name: 'api'
params: {
appName: 'api-prod'
skuName: 'P1v3'
}
}Keep environments as parameter files over one module set rather than copied templates per environment. Copied templates drift, and the drift is discovered during an incident when staging and production turn out not to match.
Related
Interview angle 5
- “Bicep or Terraform on Azure?” - Bicep if the estate is Azure-only, because there is no state file to manage and new resources are supported the day they ship. Terraform if anything else is in the estate, since running one tool and one set of habits beats a per-cloud split.
- “Why does Bicep not need a state file?” - it compiles to ARM, and Azure Resource Manager already records what exists, so the desired state is compared against the platform rather than a local record. That removes state locking, state drift, and secrets in plaintext state.
- “What is the equivalent of
terraform plan?” -az deployment group what-if, run in CI on a merge request so the diff is reviewed before apply. It is noisier than Terraform’s plan and can report properties as changing when they will not, but a reported deletion should never be dismissed. - “What is the difference between incremental and complete mode?” - incremental leaves undeclared resources alone; complete deletes anything in the resource group the template does not declare. Complete makes the template authoritative and will remove resources someone created in the portal.
- “How do you handle multiple environments?” - one module set with per-environment parameter files, not copied templates. Copies drift, and the drift surfaces during an incident when staging turns out not to match production.