Azure

ARM Templates to Bicep Migration Guide: Decompile, Manual Adjustment, Phased Migration, and What-If

2026-05-24
NicheeLab Editorial Team

Migrating from Azure's traditional IaC format, ARM templates, to its successor Bicep is already the de facto standard for new projects. This article lays out a practical guide for migrating existing ARM assets to Bicep in phases — focused on using az bicep decompile, applying manual adjustments, following a phased migration roadmap, and verifying with What-If.

Why Migrate to Bicep

ItemARM JSONBicep
FormatJSON (verbose)DSL (concise)
Code volumeBaseline~50% less
ReadabilityLowHigh
IntelliSenseLimitedStrong
Type checkingWeakStrong
ModularizationLinked TemplateModule (concise)
Microsoft recommendationLegacyPrimary recommendation

Microsoft positions Bicep as the recommended IaC tool for Azure, so new projects should default to Bicep. Existing ARM assets are best migrated gradually (no big-bang rewrite needed).

How to Use az bicep decompile

Command to automatically convert existing ARM JSON to Bicep:

az bicep decompile --file template.json

The output is saved as a template.bicep file.

Post-conversion Verification Steps

  1. Review warnings: BCP warnings indicate complex expressions or custom functions that need manual adjustment
  2. Re-transpile and diff: converts back to ARM JSON; diff it against the original ARM JSON (they should match) az bicep build
  3. What-If verification: az deployment group what-if previews the apply result and lets you verify there are no unexpected changes

Even for simpler templates, 80-90% conversion is automatic, with the remaining 10-20% requiring manual adjustment — that's the realistic pattern.

Cases That Require Manual Adjustment

Common cases that Bicep decompile cannot fully automate:

  1. Replace ARM variables with Bicep var declarations (hand-optimize complex expressions)
  2. Refactor copy loops into Bicep for loops (more readable)
  3. Break nested templates into Bicep Modules (better reusability)
  4. Replace user-defined functions with Bicep's userDefinedFunction (added in Bicep 2024)
  5. Adjust symbolic names: replace ARM's resourceId function with Bicep resource symbol references
  6. Optimize conditional resources to Bicep's if syntax
  7. Add type annotations to outputs

Example: ARM copy loop → Bicep for loop

ARM (Before)

{
  "type": "Microsoft.Storage/storageAccounts",
  "apiVersion": "2023-01-01",
  "name": "[concat('stg', copyIndex())]",
  "copy": {
    "name": "storageLoop",
    "count": 3
  },
  ...
}

Bicep (After)

resource storage 'Microsoft.Storage/storageAccounts@2023-01-01' = [for i in range(0, 3): {
  name: 'stg${i}'
  ...
}]

Recommended Phased Migration Steps

Big-bang migration (converting everything at once) is not recommended. A phased approach is the standard.

PhaseDurationAction
Phase 11-2 monthsStandardize new development on Bicep while keeping existing ARM. Build organization-standard templates and a Module library
Phase 23-6 monthsMigrate frequently maintained ARM templates first (weekly/monthly deployments)
Phase 36-12 monthsMigrate lower-frequency ARM templates (annual updates)
Phase 412+ monthsLeave untouched ARM templates as-is (low migration ROI)

Microsoft itself accepts continued use of existing ARM, so there's no need to force a full rewrite. Set the pace based on your team's Bicep proficiency and capacity.

Refactoring for Modularization

Refactor ARM nested templates and linked templates into Bicep Modules.

Recommended Directory Structure

infra/
├── main.bicep              # Entry point
├── main.parameters.json    # Per-environment parameters
├── modules/
│   ├── network.bicep       # VNet / NSG / Subnet
│   ├── storage.bicep       # Storage Account
│   ├── compute.bicep       # VM / App Service / AKS
│   └── identity.bicep      # Managed Identity / Key Vault
└── README.md

Key Technologies

  • Customize Azure Verified Modules (AVM) — Microsoft's officially verified Modules
  • Publish and version-manage Modules through an internal Bicep Registry backed by Azure Container Registry
  • Improve type safety with Bicep 2024 user-defined types
  • Visualize dependencies with Bicep Visualizer (VS Code extension)

What-If Deployment Verification

Running What-If before any production deployment is essentially mandatory. In Bicep migration projects, the critical step is verifying with What-If that the new Bicep deployment matches the original ARM deployment.

az deployment group what-if \
  --resource-group myRG \
  --template-file main.bicep \
  --parameters main.parameters.json

Output Categories

  • + Create: new resource
  • - Delete: deletion
  • ~ Modify: modification (with diff)
  • = NoChange: no change
  • * Deploy: deploy only (idempotent)

The modern best practice is to wire What-If into the CI/CD pipeline and run it automatically during pull request reviews.

Bicep Linter

az bicep lint runs static analysis on Bicep code.

Key Rules

  • no-hardcoded-location: parameterize location instead of hardcoding it
  • no-unused-parameters / no-unused-variables: detect unused elements
  • no-loc-expr-outside-params: keep location expressions in parameters
  • prefer-interpolation: prefer string interpolation over concat
  • explicit-values-for-loc-params: require explicit parameter defaults
  • protect-commandtoexecute-secrets: prevent secret exposure on the command line

Project-specific rules are configurable via bicepconfig.json. Running Lint in your CI/CD pipeline keeps code quality high. The VS Code Bicep extension surfaces Lint results in real time, giving developers instant feedback as they code.

CI/CD Pipeline Integration

Standard CI/CD pipeline pattern after Bicep migration:

  1. Lint: az bicep lint
  2. Build: az bicep build (generate ARM JSON, validation)
  3. What-If: az deployment group what-if
  4. Manual Approval (production environment)
  5. Deploy: az deployment group create

See the Bicep tutorial for the full CI/CD integration pattern.

Migration Best Practices

  1. Phased migration: avoid big-bang conversion and prioritize
  2. Default new development to Bicep; migrate existing ARM gradually
  3. az bicep decompile for auto-conversion, then manual adjustment
  4. Optimize to idiomatic Bicep using symbolic names, for loops, and modularization
  5. Always verify conversion results with What-If
  6. Automate Lint / Build / What-If in the CI/CD pipeline
  7. Leverage Azure Verified Modules (AVM)
  8. Centrally manage Modules through an internal Bicep Registry
  9. Use the VS Code Bicep extension for real-time development support
  10. Spread Bicep skills through regular team study sessions

Related Certifications

Frequently Asked Questions

Why migrate from ARM templates to Bicep?

ARM templates are Azure's traditional IaC format, but their verbose JSON syntax, poor readability, and limited modularity have long been pain points. Bicep (GA 2021) was designed as the successor to ARM: it transpiles 1:1 to ARM JSON while reducing code volume by roughly 50% and adding IntelliSense, type checking, and a proper Module system. Microsoft now positions Bicep as the recommended IaC tool for Azure, making it the default choice for new projects. Official Microsoft guidance recommends gradual migration of existing ARM assets (no big-bang rewrite required). Long-term maintainability and easier onboarding for new team members make the migration well worth it.

How do you use Bicep decompile?

Run az bicep decompile --file template.json to automatically convert an existing ARM JSON file into Bicep. The output is saved as template.bicep. Post-conversion checks: 1) Review warnings (BCP warnings are common, indicating complex expressions or custom functions that need manual adjustment); 2) Re-transpile the generated Bicep back to ARM JSON with az bicep build and diff it against the original ARM JSON (they should match); 3) Run az deployment group what-if (the equivalent of terraform plan) to preview the apply result and check for unexpected changes. Complex templates (nested copy loops, user-defined functions, etc.) require manual adjustment. Even for simpler templates, 80-90% conversion is automatic, with the remaining 10-20% needing manual tweaks — that's the realistic pattern.

What cases require manual adjustment?

Common cases that Bicep decompile cannot fully automate: 1) Replacing ARM variables with Bicep var declarations (complex expressions need hand-optimization); 2) Refactoring copy loops into Bicep for loops (more readable); 3) Breaking nested templates into Bicep Modules (better reusability); 4) Converting user-defined functions to Bicep's userDefinedFunction (added in Bicep 2024); 5) Adjusting symbolic names (replacing ARM's resourceId function with Bicep resource symbol references); 6) Optimizing conditional resources (the condition property) to Bicep's if syntax; 7) Adding type annotations to outputs. These are all about rewriting auto-converted output into more idiomatic Bicep — an essential step for maximizing readability and maintainability.

What are the recommended steps for gradual migration?

Big-bang migration (converting everything at once) is not recommended. The recommended phased approach: Phase 1 (1-2 months): standardize all new development on Bicep while keeping existing ARM in place. Build organization-standard templates and a Module library. Phase 2 (3-6 months): migrate frequently maintained ARM templates first (weekly/monthly deployments) using bicep decompile plus manual adjustment. Phase 3 (6-12 months): migrate lower-frequency ARM templates (annual updates). Phase 4 (12+ months): leave untouched ARM templates as-is (low migration ROI). Microsoft itself accepts continued ARM use, so there's no need to force a full rewrite. Set the pace based on your team's Bicep proficiency and capacity.

How do you approach Bicep modularization?

Refactor ARM nested templates and linked templates into Bicep Modules. Standard patterns: 1) Use main.bicep as the entry point with parameters.bicepparam for per-environment configuration; 2) Place per-feature Modules under modules/ (network.bicep, compute.bicep, storage.bicep, identity.bicep); 3) Customize Azure Verified Modules (AVM) — Microsoft's officially verified Modules that follow industry best practices; 4) Publish and version-manage Modules through an internal Bicep Registry backed by Azure Container Registry; 5) Improve type safety with Bicep 2024 user-defined types; 6) Visualize dependencies with Bicep Visualizer (VS Code extension). Modularization keeps even large Bicep projects maintainable — Bicep's true value comes through only when Module design is done well.

Is What-If deployment a must-have?

Running What-If before any production deployment is essentially mandatory. The command az deployment group what-if --resource-group myRG --template-file main.bicep --parameters main.parameters.json previews exactly what will change before you actually deploy. Output categories: + Create (new), - Delete, ~ Modify (changes), = NoChange, and * Deploy (deploy only). In Bicep migration projects, the critical step is verifying with What-If that the new Bicep deployment matches the original ARM deployment. The modern best practice is to wire What-If into the CI/CD pipeline and run it automatically during pull request reviews. It catches unexpected resource deletions or configuration overwrites in advance — it's a lifeline for preventing production incidents.

How do you use the Bicep Linter?

az bicep lint runs static analysis on Bicep code. Built-in rules include: 1) no-hardcoded-location (parameterize location instead of hardcoding it); 2) no-unused-parameters / no-unused-variables (detect unused elements); 3) no-loc-expr-outside-params (keep location expressions in parameters); 4) prefer-interpolation (favor string interpolation over concat); 5) explicit-values-for-loc-params (require explicit parameter defaults); 6) protect-commandtoexecute-secrets (prevent secret exposure on the command line); plus 20+ more rules. Project-specific rules are configurable via bicepconfig.json. Running Lint in your CI/CD pipeline keeps code quality high. The VS Code Bicep extension surfaces Lint results in real time, giving developers instant feedback as they code.

Which Microsoft certifications are related?

AZ-104 (Administrator) covers Bicep / ARM in Domain 1. AZ-400 (DevOps Engineer Expert) goes deep on Bicep integration within CI/CD pipelines in Domain 3 — the flagship certification for this area. AZ-204 (Developer Associate, retiring 2026-07) covers IaC from the developer perspective, and AZ-305 (Solutions Architect Expert) covers IaC strategy selection (Bicep vs. ARM vs. Terraform) from the architect perspective. Since Bicep is the de facto standard for new Azure projects, understanding it is essential for every engineer working with Azure.

Related Articles and Technical Deep Dives

Azure Bicep チュートリアル|ARM 後継 IaC の基本構文・モジュール化・What-If・CI/CD 統合【2026 年版】

Azure 純正 IaC ツール Bicep の完全チュートリアル。ARM JSON との違い・基本構文 (param/var/resource/module/output)・モジュール化ベストプラクティス・What-If デプロイ・GitHub Actions / Azure Pipelines 統合・ARM からの移行手順・関連認定試験 (AZ-104 / AZ-204 / AZ-400 / AZ-305) を日本語で網羅。

Azure DevOps エンジニア キャリアロードマップ|AZ-104 → AZ-400 → SC-100 シニア DevOps への道【2026 年版】

Azure DevOps Engineer になるための認定取得ロードマップ完全版。AZ-900 → AZ-104 → AZ-400 の王道ルート、GitHub と Azure DevOps の両方を扱う AZ-400 の構成、Kubernetes 認定 (CKA / CKAD / CKS) との二刀流、IaC (Bicep / Terraform) 戦略、年収レンジまで日本語で網羅。

Azure Architect キャリアロードマップ|AZ-900 → AZ-305 → SC-100 シニアアーキテクトへの道【2026 年版】

Azure Solutions Architect になるための認定取得ロードマップ完全版。AZ-900 → AZ-104 → AZ-305 の王道ルート、AZ-400 / SC-100 / AZ-700 との二刀流 / 三刀流戦略、マルチクラウド対応 (AWS / GCP)、未経験から 7-12 ヶ月の学習プラン、年収レンジまで日本語で網羅。

AZ-104 完全ガイド|Microsoft Azure Administrator Associate 出題範囲・学習リソース・合格戦略【2026 年版】

Microsoft Certified: Azure Administrator Associate (AZ-104) の完全ガイド。5 ドメイン (ID・ガバナンス / Storage / Compute / Network / Monitor) の出題範囲、必須実機演習、3-4 ヶ月の合格ロードマップ、AZ-305 / AZ-400 へのキャリアパス、renewal assessment 更新法を日本語で網羅。

Technical information in this article is based on the Azure Bicep Documentation. This article is not an official Microsoft Corporation product and has no affiliation or sponsorship with Microsoft. Microsoft and Azure are trademarks of the Microsoft group of companies. Information is based on official public materials as of May 24, 2026. Always check the official pages for the latest information.

Check what you learned with practice questions

Practice with certification-focused question sets

View Azure exam prep page
Author

NicheeLab Editorial Team

NicheeLab editorial team focused on data engineering and cloud certification learning. Content is structured around practical study needs and official exam domains.


Related articles
Azure

AZ-900 Azure Fundamentals: Complete Exam Guide (2026)

Pass AZ-900 — cloud concepts, Azure architecture, management...

Azure

Azure Certification Roadmap: Which Cert to Take Next (2026)

Choose your Azure certification path — Fundamentals, Associa...

Azure

AI-901 Azure AI Fundamentals (Beta): Complete Guide (2026)

Pass AI-901 — Microsoft Foundry, generative AI, responsible ...

Azure

Microsoft Entra ID Fundamentals for Azure Certs (2026)

Entra ID basics every cert candidate needs — tenants, identi...

Azure

DP-900 Azure Data Fundamentals: Complete Guide (2026)

Pass DP-900 — relational, non-relational, analytics, Power B...

Browse all Azure articles (104)
© 2026 NicheeLab All rights reserved.