What Is Bicep?

Bicep is the native IaC solution for Azure. The default used to be ARM Templates, but Bicep solved a lot of their usability problems. It’s a domain-specific language (DSL) developed and maintained by Microsoft. A Bicep file is transparently compiled (“transpiled”) into an ARM Template before deployment — there is no Bicep runtime and no new concepts introduced in Azure itself. This means Bicep has full, day-0 coverage of every Azure resource type, and every limitation of ARM still applies underneath.

Pros

  • Natively supported by Azure — same API surface as ARM, available immediately when new features ship
  • Much more concise than ARM JSON — a 150-line ARM template often becomes ~30 lines of Bicep
  • Strong typing with excellent VS Code IntelliSense via the Bicep extension
  • Easier to read than raw JSON, with an HCL-adjacent syntax
  • Provides a registry solution for centralised, reusable modules (local, ACR, or public registry)
  • Native for loops and if conditions — no copy workarounds needed
  • Decompile existing ARM JSON to Bicep with az bicep decompile

Cons

  • What-If is not that great — preview output can be verbose and occasionally inaccurate
  • Limited by ARM template language — if ARM can’t do it, Bicep can’t either
  • Azure only — not useful for managing AWS, GCP, or on-premises resources
  • Newer ecosystem — fewer community modules compared to the Terraform Registry (growing fast)

Quick Example

param storageAccountName string
param location string = resourceGroup().location

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: storageAccountName
  location: location
  sku: { name: 'Standard_LRS' }
  kind: 'StorageV2'
  properties: {
    minimumTlsVersion: 'TLS1_2'
    allowBlobPublicAccess: false
    supportsHttpsTrafficOnly: true
  }
}

output primaryBlobEndpoint string = storageAccount.properties.primaryEndpoints.blob
az deployment group create \
  --resource-group my-rg \
  --template-file storage.bicep \
  --parameters storageAccountName=mystorageaccount123

What-If: Previewing Changes

what-if is Bicep’s (and ARM’s) mechanism for previewing changes before a deployment is applied — similar in concept to terraform plan.

az deployment group what-if \
  --resource-group my-rg \
  --template-file main.bicep \
  --parameters @main.bicepparam

What-If: Reading the Output

Symbol Meaning
+ Resource will be created
~ Resource will be modified
- Resource will be deleted
× Resource will be replaced (delete + create)
= No change
? Unsure / noisy diff

What-If: Known Gaps

Noisy diffs (properties shown as modified when they haven’t changed, due to API defaults being written back), limited awareness of nested/linked deployments, and no guaranteed ordering in the output. This is why many teams consider terraform plan the stronger preview experience — Microsoft keeps improving What-If with each ARM API version.

Installing the Bicep CLI

# Via Azure CLI (recommended)
az bicep install && az bicep upgrade

# macOS
brew install bicep

# Windows
winget install -e --id Microsoft.Bicep

Bicep Docs Bicep on GitHub Bicep Public Registry Bicep Playground


🧪 Lab — ARM to Bicep

Here’s the ARM JSON resource block from the previous module:

{
  "type": "Microsoft.Storage/storageAccounts",
  "apiVersion": "2023-01-01",
  "name": "[parameters('storageAccountName')]",
  "sku": { "name": "Standard_LRS" },
  "kind": "StorageV2",
  "properties": {
    "minimumTlsVersion": "TLS1_2",
    "allowBlobPublicAccess": false,
    "supportsHttpsTrafficOnly": true
  }
}

Finish converting it to the Bicep resource block below — fill in kind and the three properties.

📝 Quiz — Bicep

Next Up

Terraform trades Bicep’s Azure-native simplicity for multi-cloud reach and a real state file.