ARM templates vs Bicep vs Terraform
ARM templates, Bicep and Terraform are all declarative infrastructure as code: you describe the end state and the tool works out the steps. ARM templates are the JSON format Azure Resource Manager reads, Bicep is a shorter language that compiles to that same JSON, and Terraform is a separate multi-cloud tool with its own state file. The decision rule: if the scenario is Azure only and says nothing about other clouds or Terraform, the answer is Bicep; if it mentions several clouds, an existing Terraform codebase or a provider for a non-Azure service, the answer is Terraform; ARM JSON is the answer only when the question is about the template format itself.
The same storage account three times
The relationship is easiest to see in code. This Bicep file declares one storage account:
param location string = resourceGroup().location
resource sa 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: 'stexamdemo001'
location: location
sku: { name: 'Standard_LRS' }
kind: 'StorageV2'
}
Microsoft Learn shows the equivalent ARM template as a JSON document with $schema, contentVersion, parameters and a resources array, the location written as the bracketed expression [parameters('location')]. The Bicep CLI converts the first form into the second at deployment time. In Terraform the same resource is an azurerm_storage_account block, deployed through a different engine entirely.
That last point is the key to the exam answers: Bicep and ARM are two spellings of one thing, while Terraform is a different thing.
Side-by-side decision table
| ARM template (JSON) | Bicep | Terraform | |
|---|---|---|---|
| Owner | Microsoft | Microsoft, open source | HashiCorp (an IBM company); CLI under the source-available Business Source License since version 1.6 |
| Scope | Azure only | Azure only | Many clouds and SaaS, through providers |
| Talks to | Azure Resource Manager | Compiles to ARM JSON, then Resource Manager | Provider plugins (AzureRM, AzAPI) |
| New Azure features | Immediately | Immediately, every resource type and API version | AzureRM waits for provider updates; AzAPI gives day-one access |
| State | None; Azure holds it | None; Azure holds it | State file you must store and protect |
| Preview before deploy | What-if | What-if | terraform plan |
| Reuse | Linked and nested templates, template specs | Modules, template specs | Modules |
| Readability | Verbose, bracketed expressions | Concise, symbolic names | Concise HCL |
Sources for the table: Microsoft Learn on Bicep and on Terraform for Azure (links below). Two rows decide most questions. State: Bicep and ARM have no state file, because Azure itself is the record of what exists. Terraform keeps its own state and compares it with the real world, which is why teams put it in remote storage and lock it. New features: Bicep supports preview and GA resource types the moment a resource provider publishes them; Terraform’s AzureRM provider covers stable functionality, and the AzAPI provider exists to reach new Azure features through the Resource Manager APIs without waiting for a provider release.
Deployment mode: the trap hidden in ARM and Bicep
ARM and Bicep deployments run in one of two modes. Incremental is the default: resources in the template are added or updated, and resources already in the resource group but not in the template are left alone. Complete deletes anything in the resource group that the template does not mention. Microsoft now labels complete mode as not recommended, says it will be gradually deprecated, and points to deployment stacks when you need deletion to follow the template. Complete mode is also unavailable in the portal, for linked or nested templates and for subscription-level deployments.
Worked example: a resource group holds a storage account, a VM and a key vault. A template that declares only the storage account is deployed.
- Incremental: all three resources remain; the storage account is updated if properties differ.
- Complete: the VM and the key vault are deleted.
Also in incremental mode, properties you leave out of a redeployed resource are reset to defaults rather than kept, because the template always represents the final state of that resource. Run what-if first; it lists what will be created, deleted or changed.
Which one to pick in practice
- A team that works only in Azure, wants no state to manage and needs day-one support for new services: Bicep.
- A team already running Terraform for AWS or Kubernetes and wanting one workflow: Terraform with AzureRM, plus AzAPI for gaps.
- Exporting a template from the portal or converting old assets: ARM JSON, then decompile to Bicep with
az bicep decompile. - Configuring software inside a machine rather than provisioning the machine: none of these; see Ansible vs Terraform and declarative vs imperative IaC.
Which exams test this
| Exam | How it appears | Covered on this site |
|---|---|---|
| AZ-104 | Deploy and manage Azure compute resources (20–25%): read, modify and deploy ARM templates and Bicep files, export a deployment as a template and convert ARM JSON to Bicep | Compute resources |
| AZ-400 | Design and implement build and release pipelines (50–55%), infrastructure as code: define an IaC strategy with source control and automated testing and deployment, and implement desired state configuration with Azure Resource Manager and Bicep | Build and release pipelines |
| AZ-900 | Describe Azure management and governance (30–35%): describe infrastructure as code, and Azure Resource Manager with ARM templates | Management and governance |
| AI-300 | MLOps infrastructure (15–20%) and GenAIOps infrastructure (20–25%): deploy Machine Learning workspaces and Foundry infrastructure with Bicep and the Azure CLI | MLOps infrastructure and GenAIOps infrastructure |
| AZ-305 | Minor topic. Design infrastructure solutions (30–35%): recommend an automated deployment solution for applications. The outline names no IaC tool, so the comparison only comes in indirectly | Infrastructure solutions |
| 200-901 | Minor topic, Terraform only. Infrastructure and Automation (20%): describe infrastructure as code principles and the capabilities of tools such as Ansible, Terraform and Cisco NSO | Infrastructure automation |
| 200-301 | Minor topic, Terraform only, v1.1 outline (bookable until Feb 2, 2027): Automation and Programmability (10%), recognize what configuration management tools such as Ansible and Terraform do. The v2.0 outline (from Feb 3, 2027) names infrastructure as code as a management approach and keeps Ansible, but no longer names Terraform | CCNA 200-301 AI and operations explained |
Only the Microsoft outlines name ARM templates or Bicep, and none of them names Terraform; the two Cisco outlines name Terraform as a general automation tool, not as an Azure deployment option. Check the current skills outline for your exam, since wording changes between versions.
How questions are built
The trap is mixing up the engine and the syntax. “Which tool requires no state file?” is Bicep or ARM; “which tool supports multiple clouds?” is Terraform. Words that decide the answer:
- “Idempotent”, “desired state”, “declarative”: true of all three, so they never separate the options alone.
- “Delete resources not in the template”: complete mode, or better, deployment stacks.
- “Preview the changes”: what-if for ARM and Bicep, plan for Terraform.
- “Multi-cloud”, “existing HCL”: Terraform.
- “Reduce JSON complexity”, “modules”, “transparent abstraction”: Bicep.
- “Latest preview resource type immediately”: Bicep, or Terraform AzAPI.
Pipelines that run these deployments are covered in YAML pipeline basics and CI/CD explained.
Practice questions
Question 1. A team deploys an ARM template to a resource group in complete mode. The template defines one storage account. The resource group also contains a virtual machine that is not in the template. What happens to the virtual machine?
- A. It is left unchanged because only storage accounts are evaluated
- B. It is deleted
- C. It is stopped and kept
- D. It is left unchanged because what-if runs automatically first
Show answer
Answer: B
Complete mode deletes resources that exist in the resource group but are not in the template, so the VM is removed. Incremental mode, the default, would leave it untouched. Complete mode does not stop and restart resources, and a what-if run only previews the change; it does not protect anything.
Question 2. A company uses only Azure and wants infrastructure code that supports every new Azure resource type and API version the day it is released, with no state file to store or protect. Which option fits best?
- A. Terraform with the AzureRM provider
- B. ARM JSON templates written by hand
- C. Azure CLI scripts in a pipeline
- D. Bicep
Show answer
Answer: D
Bicep supports all resource types and API versions as soon as the resource provider publishes them, compiles to ARM JSON and relies on Azure for state. Terraform with AzureRM depends on provider updates and keeps a state file. Raw ARM JSON also has no state but is more verbose, and the requirement favors the language designed to replace it. Azure CLI scripts are imperative rather than declarative.
Go deeper
- What is Bicep? (Microsoft Learn)
- ARM template deployment modes (Microsoft Learn)
- Terraform on Azure overview (Microsoft Learn)
- Next on this site: Ansible vs Terraform, declarative vs imperative IaC, and the AZ-400 study plan.