AZ-900 · Describe Azure Management and Governance · Updated August 7, 2026
ARM Templates, Bicep, and Infrastructure as Code in Azure
Infrastructure as code (IaC) means defining Azure resources in machine-readable files instead of clicking through the portal by hand, so the same environment can be deployed the same way every time. In Azure, that mostly means Azure Resource Manager (ARM) templates, written as JSON, or Bicep, a simpler language that compiles down into that same JSON before Azure Resource Manager processes it. Both are declarative: you describe the end state you want, and Azure figures out how to get there.
Why teams move away from clicking through the portal
Manually configuring resources works fine for a one-off experiment, but it breaks down the moment an organization needs development, test, and production environments to match. Every administrator remembers slightly different settings, click orders vary, and small inconsistencies compound into configuration drift that’s hard to diagnose later. Infrastructure as code fixes this by turning the environment definition into a text file: the same file, deployed twice, produces the same result, and because it’s just text, it can live in a Git repository where every change goes through a pull request and a reviewable history — exactly what an auditor wants, a record of who changed what, when, and why, tied to a specific commit rather than someone’s memory of a portal session months ago.
Azure Resource Manager: the layer under everything
Azure Resource Manager (ARM) is the management and deployment service that every Azure tool ultimately talks to. Whether a request originates from the Azure portal, Azure CLI, Azure PowerShell, the REST API, or an SDK, it lands at Azure Resource Manager, which authenticates it, checks it against role-based access control and any assigned Azure Policy rules, and then creates, updates, or deletes the requested resources. This single choke point is why governance stays consistent regardless of which tool someone used: a resource lock or policy assignment on a resource group still applies even if a new resource inside it was deployed through a template instead of the portal.
ARM templates: the native format
An ARM template is a JSON file that declaratively describes the resources to deploy, their configuration, and how they relate to each other. It’s authored against a defined ARM schema and typically has four notable sections:
- Parameters — input values supplied at deployment time, letting one template serve multiple environments (a VM size for dev versus prod, for example).
- Variables — values computed or assembled from other values inside the template, used to avoid repeating the same expression in multiple places.
- Resources — the actual resource definitions being created or updated; this is the heart of the template.
- Outputs — values returned after deployment finishes, such as a newly created VM’s public IP address, which a later pipeline step can read and act on.
Templates are deployed against a target scope, usually a resource group, but sometimes a subscription, management group, or tenant, depending on what’s being provisioned.
Bicep: the same engine, friendlier syntax
Bicep is a domain-specific language, built by Microsoft specifically for Azure, that trades the bracket-heavy verbosity of hand-written JSON for a cleaner, more concise syntax. When a Bicep file is deployed, the tooling transpiles it into standard ARM JSON, and Azure Resource Manager processes that JSON exactly as it would a template someone wrote by hand — nothing about the underlying deployment mechanics changes; Bicep is purely an authoring convenience layered on top of the same engine. It supports any resource type ARM supports, is free, and deploys from Azure CLI or Azure PowerShell, or a CI/CD pipeline just like raw JSON.
| ARM template (JSON) | Bicep | |
|---|---|---|
| Authoring format | Native JSON schema | Concise DSL, transpiles to ARM JSON |
| Deployed by | Azure Resource Manager directly | Azure Resource Manager, after transpilation |
| Readability | Verbose, nested brackets | Cleaner syntax, less boilerplate |
| Resource coverage | Everything ARM supports | Everything ARM supports |
| Cost | Free | Free |
Declarative versus imperative
A declarative approach — what ARM templates and Bicep use — specifies only the desired end state and leaves Azure Resource Manager to work out the sequence of operations needed to reach it. An imperative approach, like a script of sequential Azure CLI or PowerShell commands, spells out each step explicitly and runs them in order. The practical difference shows up when something changes: a declarative template can usually be redeployed safely to reconcile drift, while an imperative script has to be re-reasoned through step by step.
Idempotency and deployment modes
A well-formed ARM or Bicep deployment is idempotent: redeploying the same template against an unchanged environment produces the same end state again rather than duplicating resources or erroring out. This is what makes templates safe to reapply as a recovery mechanism if someone makes an unwanted manual change later.
Deployment mode controls how ARM treats resources in the target resource group that aren’t listed in the template. Incremental mode, the default, only creates or updates what the template defines and leaves everything else in the group untouched — including anything created manually or by a different deployment. Complete mode goes further: it deletes any resource in the group that isn’t defined in the template, which is powerful for enforcing an exact match but risky if the group holds resources you meant to keep.
Previewing changes before they land: what-if
Before running a template against production, the what-if operation compares it against the resource group’s current state and reports exactly what would be created, changed, or deleted — without applying anything. It’s the standard safety check run immediately before a real deployment, catching an accidental delete-by-complete-mode or an unexpected change before it happens.
Reuse at scale: parameter files, linked templates, and template specs
Three features let organizations reuse templates instead of copy-pasting them:
- Parameter files separate input values from template logic, so the same template deploys to dev, test, and production just by pointing it at a different parameter file.
- Nested (linked) templates split a large deployment into smaller templates per tier — networking, database, application — with a parent template calling each child in sequence and passing outputs from one as inputs to the next.
- Template specs package a template as a versioned, first-class Azure resource, shareable and access-controlled with standard Azure RBAC rather than emailed around as a loose JSON file.
None of this bypasses governance: templates deployed against a resource group still respect any Azure Policy assignment or resource lock already in place, since everything routes through Azure Resource Manager either way.
How the AZ-900 exam tests this
- Identical dev/test/production environments with a reliable reset after a manual mistake — the answer is infrastructure as code, not manual portal steps or Advisor recommendations.
- What happens redeploying the same template twice with no changes — expect “idempotency,” not duplication or an error.
- Previewing exactly what a deployment will change before touching production — that’s the what-if operation, not a resource lock or deployment mode.
- Whether Bicep replaces Azure Resource Manager (it doesn’t) — Bicep compiles to ARM JSON; Resource Manager still does the deployment work.
- Incremental mode (only touches what’s in the template) versus complete mode (deletes anything not in the template) — watch for wording about existing, unreferenced resources being left alone versus removed.
Quick reference
- Infrastructure as code means provisioning resources through machine-readable definition files instead of manual configuration.
- Azure Resource Manager (ARM) is the deployment engine every Azure tool — portal, CLI, PowerShell, templates — ultimately goes through.
- ARM templates are native JSON; Bicep is a simpler DSL that transpiles into that same JSON before deployment.
- Both are declarative: you describe the end state, and idempotent redeployment converges resources to it without duplication.
- Incremental mode (default) only touches template-defined resources; complete mode deletes anything not in the template.
- The what-if operation previews a deployment’s impact — created, changed, deleted — without applying it.
- Parameter files, nested/linked templates, and template specs are the standard ways to reuse and share templates across environments and teams.
Understanding how ARM and Bicep fit into Azure’s broader management story is easier once you’ve seen it tested — see the full AZ-900 study guide for how this fits into all three exam domains, then work through AZ-900 practice questions that cover deployment modes, what-if, and template reuse in realistic scenario form.