Migrating to Azure Bicep
AZ-104 notes: Migrating to Azure Bicep. Covers key concepts for the Azure Administrator Associate exam.
- Structured Summary + Deep Technical Understanding
Primary technologies involved:
- Azure Bicep
- Azure Resource Manager
- Azure Cloud Shell
Official Documentation:
Bicep CLI reference:
Decompile ARM to Bicep:
Deploy Bicep with Azure CLI:
Deploy Bicep with PowerShell:
1️⃣ Big Picture: Why Migrate from ARM to Bicep?
We already know:
ARM JSON → Talks to Azure Resource Manager → Talks to Resource Providers → Deploys resources
Bicep is:
✔ A higher-level language ✔ Easier to read and write ✔ Fully compatible with ARM ✔ Automatically compiled into ARM JSON
So migration = converting existing ARM templates into cleaner Bicep files.
2️⃣ Key Tool: Azure Bicep CLI
Inside Cloud Shell (Bash):
- az bicep help
Important commands:
- These two commands enable full round-trip conversion.
3️⃣ Bicep → ARM (Build Command)
Command used:
- az bicep build --file deploy.bicep --outfile test.json
What happens:
- deploy.bicep → Compiled → test.json (ARM template generated)
- This JSON file is exactly what Azure uses during deployment.
Important:
- ✔ This happens automatically during normal Bicep deployment ✔ You can run it manually for inspection/debugging
4️⃣ Inspecting the Generated ARM Template
The generated JSON includes:
- $schema
- contentVersion
- parameters
- variables
- resources
Example components seen:
- ✔ Location parameter with default ✔ WebAppName parameter ✔ SKU variable ✔ LinuxFxVersion variable ✔ Microsoft.Web/serverfarms resource ✔ Microsoft.Web/sites resource
This confirms:
- Bicep preserves full ARM template structure.
5️⃣ ARM → Bicep (Decompile Command)
Command used:
- az bicep decompile --file test.json
Output:
- test.bicep
Important warning displayed:
- ⚠ "Best effort decompilation"
Meaning:
- Complex templates may not convert perfectly
- Manual cleanup/refactoring may be needed
- Especially true for advanced nested templates
- Docs explicitly state decompilation is not guaranteed to be 100% clean.
6️⃣ Why Decompilation Might Need Refactoring
Possible issues in complex templates:
- Nested deployments
- Linked templates
- Copy loops
- Advanced conditions
- Expressions rewritten awkwardly
- Redundant variables
After decompile:
- ✔ Always review file ✔ Simplify expressions ✔ Replace hardcoded values with parameters ✔ Improve readability
7️⃣ Full Migration Workflow (From Demo)
- Step 1 — Start with Bicep Step 2 — Build → JSON Step 3 — Decompile JSON → Bicep Step 4 — Deploy new Bicep file
Deployment command used:
- az deployment group create \
- --name DemoDeployment \
- --resource-group $rgName \
- --template-file test.bicep
This proves:
- ✔ Decompilation result is fully deployable ✔ Round-trip conversion works
8️⃣ Verifying Deployment
Command used:
- az resource list --resource-group $rgName --output table
Result showed:
- ✔ App Service Plan ✔ Web App ✔ Cloud Shell storage account
Deployment state:
- ProvisioningState = Succeeded
9️⃣ What This Demonstrates Architecturally
- Bicep is NOT a separate deployment engine.
It always becomes:
- Bicep → ARM JSON → Azure Resource Manager → Resource Providers → Resources
- Even decompiled Bicep will go through ARM when deployed.
🔟 When Should You Migrate?
You should migrate ARM to Bicep if:
✔ Templates are large and hard to maintain ✔ Teams struggle with JSON readability ✔ You want modular architecture ✔ You want easier parameter management ✔ You want better developer experience
1️⃣1️⃣ Enterprise Migration Strategy
Real-world approach:
- Export existing ARM templates
- Decompile to Bicep
Refactor Bicep:
- Extract modules
- Simplify parameters
- Improve naming
- Store in Git
- Integrate into CI/CD
- Retire legacy ARM JSON
1️⃣2️⃣ Advanced Migration Tips
✔ Use Modules
Break large templates into reusable modules:
- module webApp './webapp.bicep' = {
- name: 'webAppDeployment'
- params: {
- ...
- }
- }
✔ Replace Hardcoded Values
Convert:
- name: 'mywebapp'
Into:
- param webAppName string
- name: webAppName
✔ Use Secure Parameters
@secure()
param adminPassword string
1️⃣3️⃣ Migration Caveats
Always test in dev before production rollout.
1️⃣4️⃣ Bicep CLI Build vs Deploy
Important distinction:
Build
Only compiles Bicep → JSON No resources deployed
Deploy
- Compiles AND deploys
Example deploy via CLI:
- az deployment group create \
- --resource-group myRG \
- --template-file main.bicep
- No need to manually build first.
1️⃣5️⃣ Mental Model
Think of migration like this:
- ARM JSON = Assembly language Bicep = C#
- Decompile = reverse-engineering assembly back into C#
- It works, but it may need cleanup.
1️⃣6️⃣ Key Exam Points
✔ Bicep build converts to ARM JSON ✔ Bicep decompile converts JSON to Bicep ✔ Decompile is best-effort only ✔ Bicep fully supports all ARM features ✔ Deployment scopes include resource group, subscription, management group ✔ Underlying engine is always Azure Resource Manager
1️⃣7️⃣ Final Takeaways
- ✔ Migrating to Bicep improves maintainability ✔ Bicep is production-ready (GA) ✔ ARM knowledge is still required ✔ Decompile helps accelerate migration ✔ Always review converted templates ✔ Round-trip conversion works ✔ Azure still deploys using ARM internally
If you'd like next:
- 🏗 Full real-world ARM → Bicep refactor example
- 🔄 Large nested ARM template migration walkthrough
- 🚀 CI/CD pipeline deploying Bicep with GitHub Actions
- 📘 40 exam-style ARM & Bicep migration questions
- 🧠 Advanced Bicep modules and architecture patterns
- Tell me your goal level (exam, architect, DevOps, or enterprise).
