Azure Blueprints retirement: a migration runbook before the clock runs out
The phased retirement of Azure Blueprints starts July 31, 2026 and ends in full retirement on January 31, 2027. Here is a concrete runbook to inventory usage, export definitions, and rebuild them as deployment stacks and template specs.
Azure Blueprints (Preview) has been on borrowed time since it was first flagged for retirement in 2023. That date kept moving, which made it easy to deprioritize. It just moved for the last time. The phased retirement started on July 31, 2026, and full retirement lands on January 31, 2027. If you still have blueprint definitions or assignments in a subscription, that is a hard deadline, not a roadmap item.
The frustrating part is that the retirement doesn’t just remove a feature — it silently removes a security control. Blueprint Locks (Deny Assignments) are deleted automatically at retirement, even if you do nothing. If a team’s RBAC boundaries currently depend on those locks, that protection disappears the moment the service goes away, whether or not anyone remembers it’s there.
The phased timeline
Four dates matter, and each one closes off a different capability:
| Date | What stops working |
|---|---|
| July 31, 2026 | New blueprint definitions and versions can no longer be created |
| October 31, 2026 | Existing definitions can no longer be modified; new assignments can no longer be created |
| December 31, 2026 | Existing assignments can no longer be modified |
| January 31, 2027 | Blueprints is retired: the API stops responding, portal access is removed, Blueprint Locks are removed automatically, and any definitions, versions, and assignments you haven’t exported are permanently deleted |
One detail worth repeating because it’s easy to miss: resources that were originally deployed by a blueprint are not deleted at retirement. They stay exactly where they are. What disappears is the management layer around them — the definitions, the assignments, and critically, the deny-assignment locks that were enforcing “don’t touch this without going through the blueprint.” After January 31, 2027, those resources are just resources, governed by whatever standing RBAC applies to their scope.
Step 1: find out where you’re exposed
Before touching anything, inventory usage. Two places to check:
- Azure Advisor surfaces a recommendation flagging subscriptions and management groups that still have Blueprints in use.
- The Azure Blueprints blade in the portal lists definitions and assignments directly, scoped to whatever subscription or management group you’re viewing.
If you manage more than a handful of subscriptions, don’t rely on manually opening the blade for each one — pull the Advisor recommendation across your tenant first, then confirm scope by scope.
Step 2: understand what replaces what
Azure Blueprints did two jobs that Microsoft has split into two purpose-built, generally available services:
- Storing and versioning templates → template specs (or a Git repository, if you prefer templates-as-code with PR review).
- Assigning, deploying, managing lifecycle, and locking resources → Azure Deployment Stacks.
In most migrations you use both together: store the converted template as a template spec, then deploy and govern it with a deployment stack. Deployment stacks are the direct replacement for blueprint assignments, including the deny-assignment locking behavior — I covered the mechanics of stacks in more depth in Azure Deployment Stacks: Bicep’s missing lifecycle layer. This post focuses specifically on getting existing blueprints out and rebuilt correctly.
Step 3: export what you have
Blueprint definitions are exported with the Az.Blueprint PowerShell module — there is no
Azure CLI equivalent, so PowerShell is required for this step regardless of your usual tooling.
# Get a reference to the definition you want to export
$bpDefinition = Get-AzBlueprint -SubscriptionId '<subscription-id>' -Name 'MyBlueprint' -Version '1.1'
# Export it to a local folder as JSON
Export-AzBlueprintWithArtifact -Blueprint $bpDefinition -OutputPath 'C:\Blueprints'
This produces a blueprint.json definition file plus an artifacts subfolder containing the
policy assignments, role assignments, and ARM templates that made up the blueprint. Do this for
every definition you intend to keep — anything not exported before January 31, 2027 is gone for
good.
Step 4: convert artifacts into a Bicep template
There’s no automated converter; each exported artifact maps to a specific ARM resource type you declare in Bicep:
- Role assignment artifacts →
Microsoft.Authorization/roleAssignmentsresources. - Policy assignment artifacts →
Microsoft.Authorization/policyAssignmentsresources (embedpolicyDefinitionsinline if the blueprint defined custom policies). - ARM template artifacts → Bicep modules, nested templates, or template-linked deployments.
- Sequencing/locking → replaced by the deployment stack’s
DenySettingsMode, not by anything in the template itself.
A minimal migrated template, deployed at subscription scope, looks like this:
targetScope = 'subscription'
param roleAssignmentName string = 'myTestRoleAssignment'
param roleDefinitionId string = guid(roleAssignmentName)
param principalId string = guid('myTestId')
param policyAssignmentName string = 'myTestPolicyAssignment'
param policyDefinitionID string = '/providers/Microsoft.Authorization/policyDefinitions/06a78e20-9358-41c9-923c-fb736d382a4d'
param rgName string = 'myTestRg'
param rgLocation string = deployment().location
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(roleAssignmentName)
properties: {
principalId: principalId
roleDefinitionId: roleDefinitionId
}
}
resource policyAssignment 'Microsoft.Authorization/policyAssignments@2025-03-01' = {
name: policyAssignmentName
scope: subscriptionResourceId('Microsoft.Resources/resourceGroups', resourceGroup().name)
properties: {
policyDefinitionId: policyDefinitionID
}
}
resource rg1 'Microsoft.Resources/resourceGroups@2025-04-01' = {
name: rgName
location: rgLocation
}
module vnet 'templates/bicep/vnet.bicep' = {
name: uniqueString(rgName)
scope: rg1
params: { location: rgLocation }
}
If you want the template stored and versioned in Azure — the role blueprint definitions used to play — publish it as a template spec first, then point the deployment stack at the template spec rather than a local file.
Step 5: deploy through a stack, not a plain deployment
This is the step that’s easy to get wrong under deadline pressure: deploying the converted
template directly with az deployment sub create gets your resources back, but gives you none of
the lifecycle management or locking that justified using Blueprints in the first place. Deploy it
through a stack instead:
az stack sub create \
--name 'migrated-platform-blueprint' \
--location 'westeurope' \
--template-file './main.bicep' \
--action-on-unmanage 'deleteResources' \
--deny-settings-mode 'denyDelete'
--deny-settings-mode denyDelete (or denyWriteAndDelete for stricter environments) is your
replacement for blueprint locks. Without it, you’ve technically migrated the deployment, but not
the governance — exactly the gap that causes surprises six months later when someone deletes a
resource nobody remembered was supposed to be protected.
If specific identities legitimately need to bypass the lock — a CI/CD service connection, a policy remediation identity — exclude them explicitly rather than loosening the mode:
az stack sub create \
--name 'migrated-platform-blueprint' \
--location 'westeurope' \
--template-file './main.bicep' \
--action-on-unmanage 'deleteResources' \
--deny-settings-mode 'denyDelete' \
--deny-settings-excluded-principals '<pipeline-identity-object-id>'
Up to five principals can be excluded directly; beyond that, consolidate them into a Microsoft Entra group and exclude the group instead.
What “good enough” looks like if you’re short on time
Not every blueprint deserves a full rebuild before the deadline. If a subscription is itself scheduled for decommissioning on a near-term timeline, exporting the definitions for the record and applying standard Azure resource locks is an acceptable stopgap — Microsoft’s own guidance allows for this. But for anything that outlives the retirement date, do the full migration to a deployment stack. Standing resource locks don’t give you drift detection, lifecycle cleanup, or per-principal exclusions; they’re a lock and nothing else.
The takeaway
Treat July 31, 2026 as the day the clock started, not the day something breaks — the real pain lands in stages, and the most damaging one (silent removal of your deny-assignment locks) happens automatically at the very end, with no action required from anyone. Start with the Advisor inventory this week, export every definition you need to keep, and prioritize migrating any blueprint whose locking behavior you actually depend on — that’s the capability that quietly vanishes if you wait for the portal blade to disappear before reacting.
Sources & further reading: Azure Blueprints retirement, Azure Blueprints retirement FAQ, Migrate blueprints to deployment stacks, Import and export blueprints with PowerShell, Create and deploy Azure deployment stacks in Bicep.