Azure Landing Zones Accelerator Skill
Deploy Azure Landing Zones using the ALZ Accelerator with Azure Verified Modules (AVM). This skill captures the recommended workflow, decision framework, and best practices from the ALZ core team.
Key Concepts
AVM (Azure Verified Modules): An infrastructure-as-code standard for deploying Azure resources following best practices. AVM has resource modules (single resources) and pattern modules (complex architectural patterns composed from resource modules). AVM is the only recommended way to deploy Azure Landing Zones infrastructure.
ALZ Accelerator: A tool that bootstraps the entire Azure Landing Zone deployment including CI/CD pipelines, version control, and infrastructure configuration. It uses AVM modules under the hood.
Deployment Stacks (Bicep): Used by the Bicep accelerator to handle resource lifecycle management, eliminating the pain of manually managing policy assignments and resource deletions.
Decision Framework: Bicep vs Terraform
Guide the user through this decision before proceeding with deployment.
When to Choose Terraform
- Team already has Terraform expertise
- Multi-cloud strategy (AWS, GCP, Azure) — avoids learning two IaC languages
- Terraform ALZ modules are more mature (released ~early 2025) with full configuration via tfvars
- Need for state-based drift detection
When to Choose Bicep
- Azure-only organization with no multi-cloud plans
- Team familiar with ARM templates or Azure-native tooling
- No state file to manage (pro and con — simpler ops but less drift visibility)
- Microsoft ARM/Bicep product groups recommend Bicep for Azure-only shops
- Bicep ALZ released ~Feb 2026 with full AVM support, deployment stacks, and customizable modules
Neutral Position
- Both use AVM modules — same underlying resource definitions
- Both are supported by the accelerator with identical bootstrapping UX
- The gap between them is closing rapidly in 2026
- Default recommendation: Match the team's existing skills
Accelerator Deployment Workflow
Prerequisites
Install the ALZ PowerShell module:
Install-Module -Name ALZ
Ensure you have:
- Azure CLI or PowerShell authenticated
- GitHub PAT or Azure DevOps PAT (depending on VCS choice)
- At least 4 platform subscriptions: Management, Connectivity, Identity, Security
- A bootstrap subscription for state storage and identities
Step 1: Launch the Accelerator
Deploy-Accelerator
The accelerator runs interactively with guided prompts. No parameters are required (as of the latest release).
Step 2: Software Checks
The accelerator validates required software is installed. Address any missing dependencies before proceeding.
Step 3: Choose Cache Location
Select where to store temporary files during setup. The default is usually fine.
Step 4: IaC Language Selection
Choose between:
- Terraform — More mature configuration, everything via tfvars
- Bicep — Azure-native, no state file, deployment stacks for lifecycle management
Step 5: Version Control & CI/CD Platform
Choose from:
- GitHub (default, recommended)
- Azure DevOps
- Local filesystem (for custom bootstrapping)
Step 6: Connectivity Scenario
Select the networking topology:
- Hub and Spoke — Traditional hub-spoke with VNet peering (most common)
- Virtual WAN — Azure Virtual WAN managed hub
- Multi-region variants of the above
Step 7: Interactive Configuration
The accelerator queries Azure for your existing resources and presents selection prompts:
- Bootstrap region — Where to deploy state storage and identities
- Root management group — Parent MG for the ALZ hierarchy
- Platform subscriptions:
- Management subscription (Log Analytics, monitoring)
- Identity subscription (Active Directory, DNS)
- Connectivity subscription (Hub VNet, Firewall, VPN/ER gateways)
- Security subscription (Sentinel, Defender)
- Bootstrap subscription — For Terraform state storage and managed identities
Step 8: Naming Convention
Accept defaults or customize resource naming patterns for the bootstrap resources.
Step 9: Runner Configuration
Choose between:
- Self-hosted runners — Recommended for private networking
- Microsoft-hosted runners — Simpler but requires public endpoints
If self-hosted, choose whether to enable private networking (storage accounts not publicly accessible).
Step 10: Authentication
Provide:
- Personal Access Token — GitHub PAT or Azure DevOps PAT (stored as environment variable, never in config files)
- GitHub/ADO organization name
- Apply approver — Username that approves plan-to-apply stage
Step 11: Review & Open in IDE
The accelerator generates configuration files and opens them in VS Code. Review and update:
- Platform landing zone config:
- Primary and secondary deployment regions (e.g., UK South, UK West)
- Defender email security contact
- Sensitive values are stored as environment variables in the current terminal session, not in plain text files
Step 12: Bootstrap Deployment
Confirm the configuration is complete. The accelerator bootstraps:
- State storage (Terraform) or deployment stack (Bicep)
- Managed identities for CI/CD
- GitHub repos/Azure DevOps projects with pipelines
- Branch policies and approvals
Post-Deployment
After the accelerator completes:
- CI/CD pipelines are created in your chosen VCS
- Plan/What-If stage runs automatically on PR
- Apply/Deploy stage requires approval from the configured approver
- Subsequent changes are made through the configuration files and pushed through the pipeline
AVM Module Architecture
The ALZ deployment uses these key AVM pattern modules:
| Module |
Purpose |
| Management Groups |
Hierarchy: Tenant Root → Platform (Mgmt, Conn, Identity) → Landing Zones (Corp, Online) |
| Management |
Log Analytics workspace, Automation Account, monitoring |
| Connectivity (Hub-Spoke) |
Hub VNet, Azure Firewall, VPN/ER Gateways, DNS |
| Connectivity (vWAN) |
Virtual WAN, Virtual Hubs, routing |
| Identity |
DNS zones, domain controllers networking |
| Policy |
Azure Policy assignments, custom policy definitions |
You can use these modules standalone (compose them yourself) or through the accelerator (recommended path).
Rules
- Always use AVM modules — Never deploy ALZ resources with raw azurerm/azapi resources when an AVM module exists
- Use the accelerator — Don't manually compose the modules unless you have a specific reason; the accelerator handles bootstrapping, CI/CD, and configuration
- Match team skills — Don't push Terraform on a Bicep team or vice versa
- Private networking for production — Use self-hosted runners with private networking for any production deployment
- Never store PATs in config files — The accelerator uses environment variables for sensitive values; maintain this pattern
- Four platform subscriptions minimum — Management, Connectivity, Identity, Security — don't collapse them
- Plan before apply — Always review the plan/what-if output before approving deployment
- Customize via config, not module edits — For Terraform, all customization goes through tfvars. For Bicep, you can edit modules directly but prefer the config approach when possible
Troubleshooting
| Issue |
Resolution |
| Deployment stacks bugs (Bicep) |
Known limitations — what-if not fully supported. Check ALZ GitHub issues |
| Policy assignment conflicts |
Use the separated custom vs default policy structure (Bicep 2026 release) |
| State file management (Terraform) |
State is bootstrapped automatically; don't manually modify the backend config |
| Upgrade pain from old ALZ versions |
The new Bicep release decouples your customizations from upstream modules |
Resources
- Questions form:
aka.ms/alz/quests
- ALZ documentation:
aka.ms/alz
- AVM registry:
aka.ms/avm
- ALZ Accelerator docs:
aka.ms/alz/accelerator
Gotchas
- Bicep
what-if is best-effort — nested deployments may show resources as "Create" when they exist; trust ARM deploy output, not what-if alone.
- AVM module versions pin at deploy time — an outdated
version: parameter pulls a months-old release with bugs you fixed locally.
- Management group ID is global — choosing a name collision returns 409 mid-deploy, halfway through other deployments.
- Default policy assignments include audit effects that flood activity logs in non-prod — disable explicitly or noise drowns real signal.
- Subscription quotas check at create-time, not validation-time — what-if passes, create fails with quota error 5 min in.
- Bicep template specs vs raw .bicep: template specs are versioned in ARM; raw .bicep deploys skip that versioning entirely.
1---2name: alz-accelerator3description: Deploy Azure Landing Zones using the ALZ Accelerator with AVM (Azure Verified Modules). Use this skill whenever the user mentions Azure Landing Zones, ALZ, Azure landing zone accelerator, AVM modules for landing zones, deploying management groups, hub-and-spoke networking, Virtual WAN, platform landing zones, or asks about Bicep vs Terraform for Azure infrastructure. Also trigger when the user wants to bootstrap CI/CD for Azure platform deployment, set up management groups hierarchy, or deploy connectivity/identity/management platform subscriptions.4---5
6# Azure Landing Zones Accelerator Skill
7
8Deploy Azure Landing Zones using the ALZ Accelerator with Azure Verified Modules (AVM). This skill captures the recommended workflow, decision framework, and best practices from the ALZ core team.
9
10## Key Concepts
11
12**AVM (Azure Verified Modules):** An infrastructure-as-code standard for deploying Azure resources following best practices. AVM has resource modules (single resources) and pattern modules (complex architectural patterns composed from resource modules). AVM is the only recommended way to deploy Azure Landing Zones infrastructure.
13
14**ALZ Accelerator:** A tool that bootstraps the entire Azure Landing Zone deployment including CI/CD pipelines, version control, and infrastructure configuration. It uses AVM modules under the hood.
15
16**Deployment Stacks (Bicep):** Used by the Bicep accelerator to handle resource lifecycle management, eliminating the pain of manually managing policy assignments and resource deletions.
17
18## Decision Framework: Bicep vs Terraform
19
20Guide the user through this decision before proceeding with deployment.
21
22### When to Choose Terraform
23
24- Team already has Terraform expertise
25- Multi-cloud strategy (AWS, GCP, Azure) — avoids learning two IaC languages
26- Terraform ALZ modules are more mature (released ~early 2025) with full configuration via tfvars
27- Need for state-based drift detection
28
29### When to Choose Bicep
30
31- Azure-only organization with no multi-cloud plans
32- Team familiar with ARM templates or Azure-native tooling
33- No state file to manage (pro and con — simpler ops but less drift visibility)
34- Microsoft ARM/Bicep product groups recommend Bicep for Azure-only shops
35- Bicep ALZ released ~Feb 2026 with full AVM support, deployment stacks, and customizable modules
36
37### Neutral Position
38
39- Both use AVM modules — same underlying resource definitions
40- Both are supported by the accelerator with identical bootstrapping UX
41- The gap between them is closing rapidly in 2026
42- **Default recommendation:** Match the team's existing skills
43
44## Accelerator Deployment Workflow
45
46### Prerequisites
47
481. Install the ALZ PowerShell module:
49
50 ```powershell
51 Install-Module -Name ALZ
52 ```
53
542. Ensure you have:
55 - Azure CLI or PowerShell authenticated
56 - GitHub PAT or Azure DevOps PAT (depending on VCS choice)
57 - At least 4 platform subscriptions: Management, Connectivity, Identity, Security
58 - A bootstrap subscription for state storage and identities
59
60### Step 1: Launch the Accelerator
61
62```powershell
63Deploy-Accelerator
64```
65
66The accelerator runs interactively with guided prompts. No parameters are required (as of the latest release).
67
68### Step 2: Software Checks
69
70The accelerator validates required software is installed. Address any missing dependencies before proceeding.
71
72### Step 3: Choose Cache Location
73
74Select where to store temporary files during setup. The default is usually fine.
75
76### Step 4: IaC Language Selection
77
78Choose between:
79
80- **Terraform** — More mature configuration, everything via tfvars
81- **Bicep** — Azure-native, no state file, deployment stacks for lifecycle management
82
83### Step 5: Version Control & CI/CD Platform
84
85Choose from:
86
87- **GitHub** (default, recommended)
88- **Azure DevOps**
89- **Local filesystem** (for custom bootstrapping)
90
91### Step 6: Connectivity Scenario
92
93Select the networking topology:
94
95- **Hub and Spoke** — Traditional hub-spoke with VNet peering (most common)
96- **Virtual WAN** — Azure Virtual WAN managed hub
97- **Multi-region** variants of the above
98
99### Step 7: Interactive Configuration
100
101The accelerator queries Azure for your existing resources and presents selection prompts:
102
1031. **Bootstrap region** — Where to deploy state storage and identities
1042. **Root management group** — Parent MG for the ALZ hierarchy
1053. **Platform subscriptions:**
106 - Management subscription (Log Analytics, monitoring)
107 - Identity subscription (Active Directory, DNS)
108 - Connectivity subscription (Hub VNet, Firewall, VPN/ER gateways)
109 - Security subscription (Sentinel, Defender)
1104. **Bootstrap subscription** — For Terraform state storage and managed identities
111
112### Step 8: Naming Convention
113
114Accept defaults or customize resource naming patterns for the bootstrap resources.
115
116### Step 9: Runner Configuration
117
118Choose between:
119
120- **Self-hosted runners** — Recommended for private networking
121- **Microsoft-hosted runners** — Simpler but requires public endpoints
122
123If self-hosted, choose whether to enable **private networking** (storage accounts not publicly accessible).
124
125### Step 10: Authentication
126
127Provide:
128
129- **Personal Access Token** — GitHub PAT or Azure DevOps PAT (stored as environment variable, never in config files)
130- **GitHub/ADO organization name**
131- **Apply approver** — Username that approves plan-to-apply stage
132
133### Step 11: Review & Open in IDE
134
135The accelerator generates configuration files and opens them in VS Code. Review and update:
136
1371. **Platform landing zone config:**
138 - Primary and secondary deployment regions (e.g., UK South, UK West)
139 - Defender email security contact
1402. **Sensitive values** are stored as environment variables in the current terminal session, not in plain text files
141
142### Step 12: Bootstrap Deployment
143
144Confirm the configuration is complete. The accelerator bootstraps:
145
146- State storage (Terraform) or deployment stack (Bicep)
147- Managed identities for CI/CD
148- GitHub repos/Azure DevOps projects with pipelines
149- Branch policies and approvals
150
151## Post-Deployment
152
153After the accelerator completes:
154
1551. **CI/CD pipelines** are created in your chosen VCS
1562. **Plan/What-If stage** runs automatically on PR
1573. **Apply/Deploy stage** requires approval from the configured approver
1584. **Subsequent changes** are made through the configuration files and pushed through the pipeline
159
160## AVM Module Architecture
161
162The ALZ deployment uses these key AVM pattern modules:
163
164| Module | Purpose |
165| ------------------------ | --------------------------------------------------------------------------------------- |
166| Management Groups | Hierarchy: Tenant Root → Platform (Mgmt, Conn, Identity) → Landing Zones (Corp, Online) |
167| Management | Log Analytics workspace, Automation Account, monitoring |
168| Connectivity (Hub-Spoke) | Hub VNet, Azure Firewall, VPN/ER Gateways, DNS |
169| Connectivity (vWAN) | Virtual WAN, Virtual Hubs, routing |
170| Identity | DNS zones, domain controllers networking |
171| Policy | Azure Policy assignments, custom policy definitions |
172
173You can use these modules standalone (compose them yourself) or through the accelerator (recommended path).
174
175## Rules
176
1771. **Always use AVM modules** — Never deploy ALZ resources with raw azurerm/azapi resources when an AVM module exists
1782. **Use the accelerator** — Don't manually compose the modules unless you have a specific reason; the accelerator handles bootstrapping, CI/CD, and configuration
1793. **Match team skills** — Don't push Terraform on a Bicep team or vice versa
1804. **Private networking for production** — Use self-hosted runners with private networking for any production deployment
1815. **Never store PATs in config files** — The accelerator uses environment variables for sensitive values; maintain this pattern
1826. **Four platform subscriptions minimum** — Management, Connectivity, Identity, Security — don't collapse them
1837. **Plan before apply** — Always review the plan/what-if output before approving deployment
1848. **Customize via config, not module edits** — For Terraform, all customization goes through tfvars. For Bicep, you can edit modules directly but prefer the config approach when possible
185
186## Troubleshooting
187
188| Issue | Resolution |
189| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
190| Deployment stacks bugs (Bicep) | Known limitations — what-if not fully supported. Check [ALZ GitHub issues](https://github.com/Azure/ALZ-Bicep/issues) |
191| Policy assignment conflicts | Use the separated custom vs default policy structure (Bicep 2026 release) |
192| State file management (Terraform) | State is bootstrapped automatically; don't manually modify the backend config |
193| Upgrade pain from old ALZ versions | The new Bicep release decouples your customizations from upstream modules |
194
195## Resources
196
197- Questions form: `aka.ms/alz/quests`
198- ALZ documentation: `aka.ms/alz`
199- AVM registry: `aka.ms/avm`
200- ALZ Accelerator docs: `aka.ms/alz/accelerator`
201
202---
203
204## Gotchas
205
206- **Bicep `what-if` is best-effort** — nested deployments may show resources as "Create" when they exist; trust ARM deploy output, not what-if alone.
207- **AVM module versions pin at deploy time** — an outdated `version:` parameter pulls a months-old release with bugs you fixed locally.
208- **Management group ID is global** — choosing a name collision returns 409 mid-deploy, halfway through other deployments.
209- **Default policy assignments include audit effects** that flood activity logs in non-prod — disable explicitly or noise drowns real signal.
210- **Subscription quotas check at create-time, not validation-time** — what-if passes, create fails with quota error 5 min in.
211- **Bicep template specs vs raw .bicep**: template specs are versioned in ARM; raw .bicep deploys skip that versioning entirely.