Learn what an Azure ARM Template is, how it works, and how to create, reuse, and deploy Azure infrastructure through JSON templates.
Creating Azure resources manually becomes difficult as infrastructure grows. A typical application may require virtual machines, networks, storage accounts, and security rules. Each resource also needs specific configuration settings.
Repeating these steps across development, testing, and production environments takes time. It can also introduce configuration differences that complicate deployments and troubleshooting.
An Azure ARM Template helps teams define and deploy infrastructure through code. Instead of configuring every resource manually, engineers describe the required resources in a JSON file. Azure Resource Manager processes that file and handles the deployment.
Azure environments often contain multiple resources that need consistent configuration across development, testing, and production. Managing each resource manually increases the risk of configuration errors and makes repeatable deployments harder. Azure Resource Manager (ARM) templates address this challenge by defining infrastructure as code. They allow teams to deploy and manage Azure resources through reusable JSON files. Organizations can also use Azure Managed Services to support the management and operation of their Azure infrastructure.
This guide explains how Azure ARM Templates work, what their components do, and how to create and deploy one. It also covers environment reuse, deployment methods, and the differences between ARM Templates and Bicep.
An Overview
- What Is an Azure ARM Template?
- Why Use Azure ARM Templates?
- How Do Azure ARM Templates Work?
- What Does an ARM Template Look Like?
- What Are the Main Components of an ARM Template?
- How to Create and Reuse Azure ARM Templates Across Environments
- How to Deploy an ARM Template in Azure
- What Are ARM Template Deployment Modes?
- ARM Templates vs Bicep: What Is the Difference?
- What Are the Common Limitations of ARM Templates?
- When Should You Use Azure ARM Templates?
- Conclusion
What Is an Azure ARM Template?
An Azure ARM Template is a JSON file that defines the Azure resources and configuration required for a deployment. It uses declarative syntax to describe the desired infrastructure. Azure Resource Manager processes the template and creates or updates the specified resources.
Azure Resource Manager (ARM) is Azure’s management and deployment service. It provides a consistent way to create, update, and manage resources.
An ARM Template is the infrastructure definition that you submit to this service. It describes the resources you need and their configuration.
For example, an application environment might require:
- A virtual network and subnet.
- A virtual machine.
- A network interface.
- A network security group.
- A storage account.
- A public IP address.
An ARM Template can define these resources and their required settings in one deployment.
The template does not contain a sequence of commands for creating each resource. Instead, it describes the intended result. ARM determines how to process the deployment.
This makes ARM Templates an infrastructure as code (IaC) approach. Teams can store templates in source control, review changes, and deploy infrastructure through automated workflows.
Why Use Azure ARM Templates?
Manual resource creation becomes harder to manage when teams maintain several Azure environments. ARM Templates provide a repeatable way to define and deploy those environments.
Here are the main reasons teams use them.
1. Maintain Consistent Configurations
Manually created resources can have different settings across environments. For example, a testing virtual machine might use a different network configuration from production.
A shared template helps standardize these settings. Teams can deploy the same resource definitions across environments.
2. Reduce Repetitive Work
Creating several resources through the Azure Portal requires repeated configuration steps. Templates allow teams to define those resources once.
They can then reuse the same definition for future deployments. This reduces repeated manual work.
3. Support Infrastructure Automation
ARM Templates can run through Azure CLI, PowerShell, and CI/CD pipelines. This allows teams to include infrastructure deployment in their release processes.
For example, a pipeline can deploy the required Azure resources before releasing an application.
4. Track Infrastructure Changes
Teams can store ARM Templates in Git repositories. This makes infrastructure changes easier to review and track.
Engineers can compare versions and identify when resource configurations changed. They can also use repository history to review earlier definitions.
5. Manage Resource Dependencies
Some Azure resources depend on others. A virtual machine, for example, needs supporting network resources.
ARM evaluates these dependencies and deploys resources in the required order. Independent resources can deploy in parallel.
These capabilities make templates useful for managing application infrastructure as it grows.
How Do Azure ARM Templates Work?
An ARM Template follows a declarative deployment process. You define the resources and their properties, then submit the template to Azure Resource Manager.
The deployment process generally follows these steps:
- Define the infrastructure: Create a JSON file containing the required resource definitions and configuration.
- Submit the template: Use the Azure Portal, Azure CLI, PowerShell, or an automation pipeline.
- Validate the deployment: ARM checks the template and evaluates the deployment request.
- Process dependencies: ARM determines the required deployment order for dependent resources.
- Deploy resources: ARM communicates with the relevant Azure resource providers.
- Return deployment results: Azure reports the deployment status and any configured output values.
Resource providers manage specific Azure resource types. For example, the Microsoft.Compute provider handles virtual machine resources. Microsoft.Storage manages storage account resources.
ARM translates template definitions into the operations required by these providers. It also coordinates resource creation and updates.
Consider a deployment that requires a virtual network, subnet, and virtual machine. The network must be available before the virtual machine can use it.
You can define these resources in one template. ARM processes their dependencies and coordinates the deployment.
What Does an ARM Template Look Like?
An ARM Template uses JSON to describe the resources required for deployment. Each resource definition includes its type, API version, name, location, and configuration.
Consider a template that creates an Azure storage account:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"type": "string",
"minLength": 3,
"maxLength": 24,
"metadata": {
"description": "Globally unique storage account name."
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
},
"storageSku": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS"
]
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-01-01",
"name": "[parameters('storageAccountName')]",
"location": "[parameters('location')]",
"sku": {
"name": "[parameters('storageSku')]"
},
"kind": "StorageV2",
"properties": {
"accessTier": "Hot"
}
}
],
"outputs": {
"storageAccountId": {
"type": "string",
"value": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
}
}
} This template defines one storage account. It also accepts deployment values instead of hardcoding the account name and location.
Here is what the main properties mean:
- $schema: Identifies the JSON schema used to validate the template structure.
- contentVersion: Specifies the version of the template itself.
- parameters: Accepts values during deployment.
- resources: Contains the Azure resources to deploy.
- type: Identifies the resource type through its resource provider.
- apiVersion: Specifies the API version used for that resource type.
- name: Defines the resource name.
- location: Specifies the Azure region.
- sku: Defines the storage account’s performance and replication option.
- kind: Identifies the storage account type.
- properties: Contains additional resource-specific settings.
- outputs: Returns selected values after deployment.
The storage account name must be globally unique. It must also follow Azure naming rules. Use a valid, available name before deploying this example.
The API version must support the resource type and configuration you need. Check the relevant Azure resource reference before choosing one.
This example shows the main template structure. Larger deployments can include variables, resource dependencies, conditions, and additional outputs.
What Are the Main Components of an ARM Template?
An ARM Template contains several sections. Each section serves a different purpose during deployment.
1. Schema
The $schema property identifies the template schema. It helps tools validate the template structure.
The schema also indicates the deployment scope. A resource group deployment uses a different schema from a subscription-level deployment.
2. Content Version
The contentVersion property identifies the version of the template. Teams can update this value when they revise the template.
It does not control the API version of individual Azure resources.
3. Parameters
Parameters allow users to provide values during deployment. They help reuse one template across different environments.
For example, a location parameter can accept different Azure regions:
"parameters": {
"location": {
"type": "string",
"defaultValue": "eastus"
}
} The resource definition can then refer to this parameter:
"location": "[parameters('location')]" You can provide a different location during deployment. The template itself does not need to change.
Parameters can also define resource names, SKU values, and other configuration settings. Use allowed values and validation rules when you need to restrict user input.
4. Variables
Variables store values that the template uses more than once. They can simplify expressions and reduce repeated configuration.
For example:
"variables": {
"storageSku": "Standard_LRS"
} A resource can refer to this variable:
"sku": {
"name": "[variables('storageSku')]"
} Variables are useful when several resources share common values. Unlike parameters, deployment users do not supply variable values.
5. Resources
The resources section defines the Azure resources to deploy. Each resource includes its type, API version, name, location, and required properties.
This section contains the main infrastructure definitions.
6. Outputs
The outputs section returns selected values after deployment. These values can include resource names, IDs, or endpoints.
For example, a template can return a storage account resource ID. Another deployment process can then use that value.
Not every template needs outputs. Include them when later steps need information from the deployment.
For a complete reference, see Microsoft’s guide to ARM Template structure and syntax.
How to Create and Reuse Azure ARM Templates Across Environments
Creating a reusable ARM Template involves separating resource configuration from environment-specific values.
For example, development, testing, and production environments may use different resource names and locations. However, they may share the same basic infrastructure design.
You can manage these differences with parameters and parameter files.
Step 1: Define the Resource Configuration
Start by listing the resources the application needs. Identify their required properties and dependencies.
For a basic application environment, this might include:
- A virtual network.
- A subnet.
- A virtual machine.
- A storage account.
- A network security group.
Create an ARM Template that defines these resources.
Step 2: Add Parameters for Environment Values
Avoid hardcoding values that change between environments. Define parameters for resource names, locations, and configuration options.
For example, development and production environments can use different storage account names. Both deployments can still use the same template.
Step 3: Create Parameter Files
Store environment-specific values in separate parameter files.
For example:
- dev.parameters.json
- test.parameters.json
- prod.parameters.json
A parameter file supplies values for the parameters defined in the template.
For the storage account example, a development parameter file could look like this:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountName": {
"value": "devstorageaccount123"
},
"location": {
"value": "eastus"
},
"storageSku": {
"value": "Standard_LRS"
}
}
} Create separate files with suitable values for testing and production. Each storage account name must be globally unique.
This allows teams to maintain one infrastructure definition. They can deploy it with different configuration values.
Step 4: Define Resource Dependencies
Some resources must exist before others can deploy. ARM uses the dependsOn property to define explicit dependencies.
For example, a network interface may require a network security group and public IP address. Its resource definition can include:
"dependsOn": [
"[resourceId('Microsoft.Network/networkSecurityGroups', parameters('nsgName'))]",
"[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpName'))]"
] ARM deploys these dependencies before the network interface. Resources without dependencies can deploy in parallel.
Use explicit dependencies only when required. Unnecessary dependencies can slow deployments and create circular dependency problems.
Step 5: Store Templates in Version Control
Keep the template and parameter files in a Git repository. This provides a history of infrastructure changes.
Teams can review updates before deployment. They can also include template validation in their development workflow.
Step 6: Test Before Deployment
Validate the template before applying changes to an Azure environment. Use deployment previews to inspect the expected changes.
This helps identify configuration problems before they affect existing resources.
How to Deploy an ARM Template in Azure
Azure supports several ways to deploy ARM Templates. The right method depends on the team’s workflow and automation requirements.
1. Deploy Through the Azure Portal
The Azure Portal provides a graphical interface for template deployment.
A typical process involves:
- Sign in to the Azure Portal.
- Open the custom deployment option.
- Select or upload the ARM Template.
- Provide the required parameter values.
- Select the target subscription and resource group.
- Review the configuration and start deployment.
- Check the deployment status.
This approach is useful for learning and occasional deployments. However, command-line tools and pipelines are better suited to repeatable automation.
2. Deploy Using Azure CLI
Azure CLI allows engineers to deploy templates from a terminal or automation script.
First, sign in to Azure:
az login Create a resource group if it does not already exist:
az group create \
--name myResourceGroup \
--location eastus Next, validate the template:
az deployment group validate \
--resource-group myResourceGroup \
--template-file azuredeploy.json \
--parameters @dev.parameters.json Validation checks the deployment request before it creates or updates resources. It does not guarantee that every runtime operation will succeed.
Then preview the proposed changes:
az deployment group what-if \
--resource-group myResourceGroup \
--template-file azuredeploy.json \
--parameters @dev.parameters.json The what-if operation predicts which resources Azure expects to create, modify, or delete. It does not make changes to existing resources.
After reviewing the results, deploy the template:
az deployment group create \
--resource-group myResourceGroup \
--template-file azuredeploy.json \
--parameters @dev.parameters.json Here is what the main command options do:
- az deployment group create starts a resource group deployment.
- –resource-group identifies the target resource group.
- –template-file specifies the ARM Template JSON file.
- –parameters supplies values from the parameter file.
The deployment identity needs permission to create or update the specified resources. The required permissions depend on the resource types in the template.
3. Deploy Using PowerShell
Azure PowerShell also supports ARM Template deployments. Engineers can use the New-AzResourceGroupDeployment command.
For example:
New-AzResourceGroupDeployment `
-ResourceGroupName "myResourceGroup" `
-TemplateFile "azuredeploy.json" `
-TemplateParameterFile "dev.parameters.json" This method is useful for teams that already manage Azure operations through PowerShell scripts.
4. Integrate Templates Into CI/CD Pipelines
Teams can include ARM Template deployment in their CI/CD workflows. A pipeline can validate the template and deploy infrastructure during a release.
A typical workflow includes:
- An engineer updates the template in a repository.
- The pipeline runs template validation.
- The pipeline previews proposed deployment changes.
- An approval step runs when required.
- The pipeline deploys the template.
- The release process verifies the deployed resources.
This approach connects infrastructure changes with application releases. It also makes deployment steps easier to review and repeat.
What Are ARM Template Deployment Modes?
ARM resource group deployments support incremental and complete deployment modes. These modes determine how Azure handles resources that already exist in the target resource group.
Incremental Mode
What the Incremental mode does is that it adds resources defined in the template. It also updates existing resources that appear in the template.
Resources outside the template remain in the resource group. However, this does not mean Azure preserves every existing property on a redeployed resource.
ARM reapplies the resource configuration defined in the template. Properties omitted from that definition can return to their default values.
Therefore, include all required non-default properties when updating existing resources.
Complete Mode
Complete mode deletes resources in the target resource group that are absent from the template. Microsoft does not recommend this mode for new deployments. It will be gradually deprecated.
Use deployment stacks when you need to manage resource deletion through ARM Templates or Bicep.
Always review proposed changes before deployment. Microsoft’s deployment mode documentation explains these behaviors in detail.
ARM Templates vs Bicep: What Is the Difference?
Bicep is a domain-specific language for deploying Azure resources. It provides the same core deployment capabilities as ARM Templates, but uses a simpler syntax.
The main difference is how engineers write infrastructure definitions.
| Feature | ARM Templates | Bicep |
|---|---|---|
| File format | JSON | Bicep language |
| Readability | Can become verbose | More concise |
| Parameters | Supported | Supported |
| Variables | Supported | Supported |
| Resource dependencies | Supported | Supported |
| Azure deployment | Directly supported | Compiled into ARM JSON |
| Best suited for | Existing JSON workflows | New Azure IaC projects |
Consider a team managing a large infrastructure deployment. An ARM Template may contain extensive JSON structures and expressions.
The equivalent Bicep file is often shorter and easier to maintain. This can make infrastructure definitions easier to review.
Microsoft recommends considering Bicep for new Azure infrastructure as code projects. However, ARM Templates remain supported and useful for existing deployments.
The choice depends on the team’s existing templates, tools, and maintenance requirements. See Microsoft’s Bicep documentation for a comparison.
What Are the Common Limitations of ARM Templates?
ARM Templates provide a structured deployment method. However, teams should understand several limitations before adopting them.
- Verbose JSON: Large templates can become difficult to read and maintain.
- Complex expressions: Nested expressions and functions can make resource definitions harder to troubleshoot.
- Dependency management: Incorrect dependencies can cause deployment failures or unnecessary delays.
- API version changes: Resource providers expose different API versions. Teams must select versions that support their required properties.
- Configuration mistakes: Incorrect resource properties, names, or parameter values can prevent successful deployments.
- Template size: Large templates may need to be divided into smaller, reusable components.
Teams can address many of these issues through modular templates, parameter files, validation, and version control.
For larger Azure environments, Bicep may also provide a more maintainable authoring experience.
When Should You Use Azure ARM Templates?
ARM Templates are useful when teams need repeatable Azure resource deployments. They are particularly relevant in environments with multiple resources and deployment stages.
Common use cases include:
- Standardized environments: Deploy consistent infrastructure across development, testing, and production.
- Application provisioning: Define the network, compute, and storage resources an application requires.
- Infrastructure automation: Include resource deployment in CI/CD pipelines.
- Disaster recovery preparation: Maintain infrastructure definitions that support rebuilding resources in a recovery environment.
- Configuration management: Track infrastructure definitions and changes through source control.
- Multi-resource deployments: Coordinate resources that depend on one another.
For example, a SaaS provider may need separate Azure environments for development and production. A reusable template can define the common infrastructure. Parameter files can supply environment-specific values.
This reduces repeated configuration work. It also makes infrastructure changes easier to review.
Conclusion
Azure ARM Templates help teams define and deploy infrastructure through reusable JSON files. They support consistent resource configurations, automation, and version-controlled infrastructure management.
Their declarative approach makes multi-resource deployments easier to coordinate. Parameters also allow teams to reuse templates across different environments.
However, large JSON templates can become difficult to maintain. Teams starting new Azure infrastructure projects should also evaluate Bicep.
The right approach depends on the existing environment, deployment workflow, and long-term maintenance needs.