Bicep vs ARM Templates
Azure Resource Manager (ARM) templates describe cloud resources in JSON. Bicep describes the same resources in a shorter, friendlier language. Both reach Azure through the same deployment engine, so a Bicep file gains nothing and loses nothing in power compared with its JSON cousin.
Picture two recipe books. One packs every step into dense wording with brackets and quotation marks on every line. The other uses short, plain sentences. Both books produce the same meal. ARM JSON plays the dense book, and Bicep plays the plain one.
A Storage Account in ARM JSON
An ARM template needs a schema link, a version number, and square-bracket expressions wrapped in quotes.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageName": { "type": "string" }
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2023-01-01",
"name": "[parameters('storageName')]",
"location": "[resourceGroup().location]",
"sku": { "name": "Standard_LRS" },
"kind": "StorageV2"
}
]
}The Same Storage Account in Bicep
Bicep drops the schema line, the quotes around keys, and the bracket syntax. The result fits in a handful of lines.
param storageName string
resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageName
location: resourceGroup().location
sku: {
name: 'Standard_LRS'
}
kind: 'StorageV2'
}How a Bicep File Reaches Azure
Azure never reads Bicep directly. The Bicep tools translate the file into ARM JSON, and Azure Resource Manager builds the resources from that JSON.
main.bicep Bicep tools main.json Azure Resource
(you write) ───► (compile step) ───► (ARM template) ───► Manager builds
your resources
The translation happens automatically during deployment. Developers rarely open the JSON output.
Key Differences at a Glance
| Area | ARM Template | Bicep |
|---|---|---|
| Language | JSON | Declarative Bicep syntax |
| Length | Long and nested | Short and flat |
| Comments | Limited support | Single-line and multi-line comments |
| References | Functions such as reference() and resourceId() | Direct symbolic names such as storage.id |
| Dependencies | Written by hand in dependsOn | Detected automatically in most cases |
| Reuse | Linked or nested templates | Modules |
| Editor help | Basic | IntelliSense, validation, and hints in Visual Studio Code |
Convert Between the Two
Existing ARM templates do not need a rewrite from scratch. The Bicep command line converts both directions.
# Turn a Bicep file into ARM JSON
az bicep build --file main.bicep
# Turn an ARM JSON file into Bicep
az bicep decompile --file template.jsonA Note on Decompiling
Decompiling gives a starting point and not a finished product. Review the generated file, rename symbolic names to something meaningful, and replace repeated values with parameters and variables.
Choosing Between Them
Pick Bicep When
New projects benefit from Bicep because the code stays readable and teammates review changes faster. Bicep supports new Azure resource types and API versions as soon as they appear.
Keep ARM JSON When
A large, stable template already runs in production and nobody plans to change it. Rewriting working code adds risk without a clear gain. Teams often convert templates one at a time as they need edits.
What Stays the Same
Resource types, API versions, property names, and deployment commands match in both formats. A developer who knows the Azure portal settings for a storage account recognizes every property in the Bicep file. Role-based access control, deployment history, and the what-if preview behave identically. Skills learned in ARM JSON transfer to Bicep, and the reverse holds as well.
Summary
ARM templates and Bicep share one deployment engine. Bicep adds cleaner syntax, direct references, automatic dependency detection, and modules. The Bicep command line compiles Bicep into JSON and decompiles JSON into Bicep, which makes a gradual move easy.
