Azure Landing Zone Accelerator: What It Deploys and Where It Hurts
Most teams hit the same wall. They have one or two Azure subscriptions, no management group hierarchy worth mentioning, and a pile of resources deployed by whoever had Contributor on the day. Then a compliance audit lands, or a new workload needs a dedicated subscription, and suddenly someone has to retrofit governance onto a flat structure that was never built for it. The Azure Landing Zone Accelerator exists to skip that retrofit.
We have deployed it in enough environments to have opinions. This note covers what the accelerator actually creates, which implementation track to choose, where the defaults quietly cause pain, and what you have to add yourself before the environment is production-ready.
What "Accelerator" Means in Practice
Microsoft publishes three main implementation paths under the Landing Zone umbrella. The portal experience at aka.ms/caf/ready walks you through a wizard and generates an ARM deployment. ALZ-Bicep is a set of orchestrated Bicep modules maintained in the Azure/ALZ-Bicep GitHub repo. ALZ-Terraform wraps the same logic in Terraform, using the Azure/caf-enterprise-scale provider module.
All three produce the same conceptual output: a management group hierarchy, Azure Policy assignments at the right scopes, a hub virtual network (or Virtual WAN if you go that route), a Log Analytics workspace, Microsoft Defender for Cloud enablement per subscription, and a set of subscriptions pre-wired into the hierarchy. The portal wizard is fine for a one-time proof-of-concept. For anything that needs to be version-controlled and re-deployable, go ALZ-Bicep or ALZ-Terraform. We default to ALZ-Bicep because the module versions align tightly with AVM (Azure Verified Modules) and the Bicep language itself has fewer abstraction layers to debug.
The Management Group Hierarchy You Are Actually Agreeing To
The default hierarchy has five levels: Tenant Root Group, a top-level MG you name (usually the org name), then Platform, Landing Zones, Decommissioned, and Sandbox. Under Platform there are three child MGs: Management, Connectivity, and Identity. Under Landing Zones there are Corp and Online.
This matters because Azure Policy assignments inherit downward. Deny policies assigned at the top-level MG apply to every subscription in your tenant, including ones that predate the accelerator. That surprises every team the first time. Before you run anything, export your existing policy state.
# snapshot policy assignments across all management groups before ALZ lands
az policy assignment list \
--scope "/providers/Microsoft.Management/managementGroups/<tenant-root-id>" \
--query "[].{name:name, scope:scope, policyDefId:policyDefinitionId}" \
-o table > pre-alz-policy-snapshot.txt
Keep that file. Post-deployment you will diff it against the new assignments to understand what changed and what your existing workloads are now subject to.
Deploying ALZ-Bicep Without Destroying Your Weekend
The ALZ-Bicep repo uses an "orchestration" layer: a set of deploy.sh scripts or GitHub Actions workflows that call each module in dependency order. There are roughly 14 modules. You do not run them individually by hand; you run the orchestration. Here is the minimal local bootstrap assuming you already have the repo cloned:
# prereqs: az CLI >= 2.60, Bicep >= 0.28, jq
az login --tenant <tenant-id>
# set your parameters file (copy from config/custom-parameters/alzDefaultValues.bicepparam)
cp config/custom-parameters/alzDefaultValues.bicepparam \
config/custom-parameters/myorg.bicepparam
# then edit myorg.bicepparam for your org prefix, location, hub address space, etc.
# deploy management groups + policies first (no subscription yet)
bash pipeline-scripts/Deploy-ALZ-Bicep.sh \
-a "config/custom-parameters/myorg.bicepparam" \
-s "management" \
-u "false"
The -u "false" flag means "do not update existing policy assignments." Set it to true on subsequent runs. We learned the hard way that leaving it true on a first run over an existing tenant will overwrite policies you set manually, and the error messages are not specific about which assignments it stomped.
Hub networking comes after the management modules finish. The hub module expects a Connectivity subscription to exist and be placed under the Platform/Connectivity MG before it runs. Sequence matters. The orchestration handles this if you use the provided GitHub Actions workflow, but if you are calling modules manually the order is: management groups, policy assignments, subscriptions vended into hierarchy, then hub networking.
Policy Assignments That Quietly Block Your Workloads
The accelerator assigns roughly 140 built-in and custom policies. Most are audit-mode. A handful are Deny. The ones that catch teams off-guard are:
Deny: Public IP on NICs attached to VMs inside the Corp landing zone. Any workload that assumed a public IP for management access will fail to deploy. You need Azure Bastion or an NVA in the hub.
Deny: Storage accounts without HTTPS-only in the Corp and Online zones. If you are lifting a legacy workload that uses http endpoints on Blob storage, it will hard-fail at the ARM layer, not the application layer. You find out when the deployment returns a RequestDisallowedByPolicy error that is easy to misread.
Audit: Subnets without NSGs everywhere. This is audit-mode by default but some org overlays flip it to Deny. Check before you assume.
The way to preview impact before deployment is the Azure Policy What-If API combined with the policy initiative definitions in the ALZ-Bicep repo. We pipe the initiative JSON through a small script that filters for "effect": "Deny" parameters and produces a human-readable list of what will block.
// example: override a specific policy effect in your parameters file
// to flip 'Deny' to 'Audit' for one policy during migration
var policyAssignmentParametersOverride = {
effect: {
value: 'Audit'
}
}
Use parameter overrides sparingly and document every one in a decision log. These overrides accumulate and create drift. Teams that arrive six months later have no idea why their Corp zone does not enforce public IP denial, and then they wonder why their audit finding exists.
Hub Networking Defaults and What to Wire After
The default hub is a hub-spoke topology with an Azure Firewall Premium SKU, an ExpressRoute gateway, and a VPN gateway. All three get deployed into the Connectivity subscription. The firewall alone runs about $1.50/hour at list price in most regions, and both gateways add another $0.60/hour combined. This is before any data processing charges.
If you are deploying a smaller environment or a sandbox, consider the Virtual WAN path or a stripped hub that skips the ExpressRoute gateway until you need it. The ALZ-Bicep hub-networking module accepts a parDeployVpnGateway and parDeployErGateway parameter. Set both to false in non-production environments.
What the accelerator does not wire for you: DNS Private Resolver (you have to add this to resolve private endpoint hostnames across spokes), custom DNS forwarder rules if you have on-premises DNS zones, Azure Monitor Baseline Alerts (the AMBA project is a separate deployment on top of ALZ), and Defender for Servers plan selection. The accelerator enables Defender for Cloud at the subscription level but leaves plan selection to you. In most environments we set Servers Plan 2 on production subscriptions and Plan 1 on Corp sandboxes to control cost.
Connecting Existing Workloads Without Breaking Them
Moving a subscription from a flat structure into the ALZ hierarchy triggers policy evaluation against everything already in that subscription. You will see a flood of compliance findings. They are almost all retroactive audit findings, not new Deny blocks, but they create noise that obscures real issues.
The cleanest migration path: move the subscription under the Decommissioned or Sandbox MG first. Let policy evaluation run and export the findings. Triage them. Fix the genuine violations. Then move the subscription to its target MG (Corp or Online) under Landing Zones.
We document this process and the associated Bicep templates in our cloud architecture practice. The key thing to get right before moving subscriptions is role assignment inheritance. Custom RBAC role assignments at the subscription level survive the move. But role assignments at the old management group scope stop applying the moment the subscription leaves. Audit those before the move, not after.
When to Call Us
If you are starting an ALZ accelerator deployment from scratch, evaluating the Virtual WAN path versus hub-spoke for a hybrid environment, or trying to move a brownfield tenant into a compliant hierarchy without a production outage, reach out at /contact.
