How Azure Resource Manager Differs from the Classic Deployment Model
Two control planes have governed Azure since its earliest days — one flat, imperative, and gone; one layered, declarative, and now the only one that exists. Understanding the difference isn't just history. It's the reason resource groups, tags, RBAC, and infrastructure-as-code work the way they do today, and it still shows up on certification exams, in architecture interviews, and in the occasional decade-old subscription nobody's touched since 2015.
Every cloud platform accumulates a first control plane and, if it lives long enough, a second one that replaces it. Azure's first was the Service Management API — what almost everyone calls the "classic" deployment model, or ASM (Azure Service Manager). It shipped with Azure's public launch and worked the way infrastructure automation worked in 2010: a flat list of resources under a subscription, managed through an XML-based API, secured by a management certificate, with no native concept of grouping, tagging, or fine-grained access control. Azure Resource Manager (ARM) arrived years later as a deliberate redesign — not a patch, a different model entirely — introducing resource groups, a JSON-based declarative API, role-based access control, and the templating foundation that Bicep and most infrastructure-as-code tooling on Azure still builds on today. For a decade, both models coexisted, and choosing between them was a real architectural decision. That decision no longer exists: classic was fully retired on August 31, 2024, and ARM is Azure's only deployment model. Understanding the difference remains useful anyway — for exams, for reading old architecture diagrams, and for recognizing decade-old subscriptions that still carry the classic model's fingerprints.
Azure Service Manager was Azure's original control plane, in use since the platform's earliest public availability around 2010. "Classic" is the informal name most documentation and engineers use; ASM is the formal one. Every resource you created — a virtual machine, a cloud service, a storage account, a virtual network — was provisioned and managed through the Service Management API, an XML-based API that predates the JSON-and-REST conventions most cloud platforms use today.
- No resource groups. Resources existed as a flat collection directly under a subscription. There was no native construct for grouping related resources together for lifecycle management or access control.
- Certificate-based authentication. Management operations were authenticated via management certificates rather than an identity provider — a model that predates the now-standard approach of Microsoft Entra ID-backed identity and role assignment.
- Coarse access control. Access was essentially binary: an account was either a co-administrator on the subscription (with full control over everything in it) or had no access at all. There was no equivalent of "read-only access to this one resource."
- Sequential, imperative operations. Deployments were a sequence of individual API calls rather than a declarative description of desired end state — closer to a script than a template.
If you ever encounter a classic resource in the Azure portal, its resource type follows a recognizable pattern — for example Microsoft.ClassicStorage/storageAccounts for a classic storage account, versus Microsoft.Storage/storageAccounts for its ARM equivalent. The word "Classic" (or "ClassicCompute," "ClassicStorage," "ClassicNetwork") in the resource provider namespace is the reliable signal, not just the resource's appearance in the portal.
Azure Resource Manager is the management layer introduced to replace ASM — not merely a newer API, but a structurally different model for how resources are organized, secured, and deployed. Every interaction with Azure today, regardless of tool — the Azure portal, Azure CLI, Azure PowerShell, the SDKs, Terraform, Bicep — goes through Resource Manager's consistent REST API surface.
- Resource groups as a first-class construct. Every ARM resource belongs to exactly one resource group, which acts as a lifecycle, access-control, and organizational boundary.
- Microsoft Entra ID-backed RBAC. Access is governed by role assignments — built-in roles like Owner, Contributor, and Reader, or custom roles — scoped to a management group, subscription, resource group, or individual resource.
- Declarative deployment. ARM templates (JSON) and Bicep (a more concise DSL that compiles to ARM JSON) describe the desired end state of a set of resources. Resource Manager reconciles current state to that description, deploying resources in parallel where dependencies allow.
- Tags, locks, and policy. Resources can carry key-value tags for cost tracking and organization, be protected with CanNotDelete or ReadOnly locks, and be governed by Azure Policy definitions enforced at deployment time.
A common point of confusion: Bicep and Terraform aren't alternatives to ARM — they're authoring layers on top of it. Bicep compiles directly to ARM JSON templates. Terraform's AzureRM provider calls the same ARM REST API that the Azure CLI and portal call. There is no path to provisioning Azure resources today that bypasses Resource Manager; the tooling differs, the underlying management plane doesn't.
Every downstream difference between the two models traces back to one architectural decision: ARM inserted a consistent management layer between tools and resources; classic did not. That single choice is what made everything else — resource groups, RBAC, tags, idempotent templates — structurally possible.
| Aspect | Classic (ASM) | Azure Resource Manager |
|---|---|---|
| Management layer | None — tools called resource-specific APIs somewhat independently | Resource Manager sits between every tool and every resource, uniformly |
| API format | XML-based Service Management API | JSON-based REST API |
| Organizing construct | Flat list under a subscription | Resource groups within a subscription |
| Deployment style | Imperative — sequential API calls | Declarative — desired-state templates, parallel deployment |
| Idempotency | Not native — reapplying a script could duplicate or fail | Native — redeploying an unchanged template is a no-op |
The single table worth bookmarking — every major dimension classic and ARM differed on, in one place.
| Category | Classic (ASM) | Azure Resource Manager |
|---|---|---|
| Authentication | Management certificates | Microsoft Entra ID (Azure AD) identities, service principals, managed identities |
| Access control | Co-administrator or nothing — subscription-wide, all-or-nothing | Role-based access control (RBAC), scoped to management group / subscription / resource group / resource |
| Resource organization | Flat list per subscription | Resource groups — a lifecycle and access-control boundary |
| Tagging | Not supported | Native key-value tags on every resource, for cost tracking and organization |
| Resource locking | Not supported | CanNotDelete and ReadOnly locks, at any scope |
| Deployment automation | Custom scripts calling sequential API operations | ARM JSON templates, Bicep, Terraform — declarative, idempotent, parallelizable |
| Governance | No native policy engine | Azure Policy — enforce/audit rules at deployment and runtime |
| Cost management | Not resource-group-scoped; limited attribution | Cost Management + tags enable granular cost attribution |
| Networking | Classic virtual networks — limited subnet/NSG capability | Full VNets, subnets, NSGs, service endpoints, private endpoints, peering |
| Storage | Classic storage accounts — single account type | Storage accounts with blob/file/queue/table services, tiers, redundancy options, RBAC per account |
| Compute | Cloud Services (classic), IaaS VMs (classic) | Virtual Machines, VM Scale Sets, Cloud Services (extended support), AKS, App Service, Container Apps |
| API surface | XML, Service Management API | JSON, REST API — consistent across portal, CLI, PowerShell, SDKs |
| Current status | Retired August 31, 2024 | Sole supported deployment model |
Microsoft's associate and expert-level Azure certifications (particularly AZ-104: Azure Administrator) have historically tested the conceptual distinction between ARM and classic, even well after classic's practical retirement, because the underlying architectural concepts — resource groups, RBAC scope, declarative deployment — are foundational to nearly everything else on the exam. Knowing this table cold is worth the study time independent of whether you'll ever touch an actual classic resource.
If there's one concept that captures what ARM added over classic, it's the resource group — a container that holds related resources for a solution, and the boundary against which most management operations (deployment, access control, deletion, cost tracking) are naturally scoped.
- Lifecycle grouping. Resources that share a lifecycle — deployed together, retired together — belong in the same resource group. Deleting a resource group deletes everything in it, which makes environment teardown (a dev/test environment, for instance) a single operation instead of a manual resource-by-resource cleanup.
- Access control boundary. A role assignment at the resource group level applies to every resource inside it, present and future — grant a team Contributor on a resource group, and they can manage everything deployed into it without needing per-resource assignments.
- Deployment scope. ARM templates and Bicep files typically deploy into a single resource group (though subscription- and management-group-level deployments exist for broader scenarios), making the resource group the natural unit of "one deployable thing."
- Region-independent container. A resource group has its own region (where its metadata is stored) but can contain resources from any region — a common point of confusion for people expecting the resource group's region to constrain what it can hold.
Resources can be moved between resource groups (and even between subscriptions, for supported resource types), but at any given moment a resource belongs to exactly one resource group — it isn't a tag-like many-to-many relationship. Design resource group boundaries around genuine lifecycle and access-control groupings (an application's full stack, an environment, a team's resources) rather than around loose thematic categories that don't reflect how the resources are actually managed.
Three specific capabilities that classic had no equivalent for at all, not a lesser version — RBAC, tags, and resource locks are structurally new, made possible directly by ARM's management-layer design.
| Capability | What it does | Classic equivalent |
|---|---|---|
| RBAC | Assigns built-in or custom roles (defining allowed actions) to identities, scoped to any level of the management hierarchy | None — co-administrator or no access |
| Tags | Key-value metadata attached to resources or resource groups, queryable and usable for cost allocation, automation, and policy targeting | None |
| Resource locks | CanNotDelete prevents deletion while allowing modification; ReadOnly prevents both | None |
| Azure Policy | Enforces or audits rules (allowed regions, required tags, allowed SKUs) at deployment time and continuously thereafter | None |
The common thread: all four depend on Resource Manager knowing about every resource through a single, consistent interface. Classic's model — where different resource types were managed through somewhat separate mechanisms with no unifying layer — had no natural place to attach a role assignment, a tag, or a policy that would apply consistently regardless of resource type.
Classic deployment was fundamentally imperative: a script issued a sequence of API calls, each one an instruction ("create this," "attach that"), and getting from empty subscription to running environment meant executing that sequence correctly, in order, with no built-in concept of "what should exist" independent of "what steps got run."
ARM templates flipped this to declarative: a JSON (or Bicep) document describes the desired end state — these resources, with these properties, these relationships — and Resource Manager figures out how to reconcile the current state of the resource group to match it, deploying resources in parallel wherever their dependency graph allows, and safely no-op-ing on a redeploy of an already-matching template.
Because ARM exposes a consistent, well-documented REST API describing resources as structured data rather than a sequence of imperative operations, third-party infrastructure-as-code tools were able to build Azure providers on top of it without needing Microsoft's cooperation beyond API access. Classic's more ad-hoc, XML-based, imperative API surface would have made an equivalent Terraform provider dramatically harder to build and maintain.
Classic's retirement wasn't sudden — it was a multi-year, phased wind-down, with different resource types retiring on different timelines as ARM equivalents matured and adoption grew.
| Milestone | Date | What happened |
|---|---|---|
| IaaS VMs (classic) deprecated | February 28, 2020 | New customers could no longer create classic VMs; existing customers could continue |
| Classic storage account management deprecated via ASM | August 31, 2021 | ARM offered full storage account functionality; classic management path began winding down |
| IaaS VMs (classic) fully retired | September 6, 2023 | Any remaining active/allocated classic VMs were stopped and deallocated |
| New classic storage account creation blocked | August 16, 2024 | No more classic storage accounts could be created by anyone |
| Classic resource providers fully retired | August 31, 2024 | ASM endpoints disabled. Classic resource providers (Cloud Services, Storage, Network, and others) stopped accepting management operations |
Microsoft's stated rationale, consistent across its retirement communications, centered on the capability gap: ARM offered simplified resource deployment through a unified management layer, resource grouping for organized access control and monitoring, and — implicitly — a platform that every newer Azure capability (Policy, Cost Management, Managed Identity, Bicep, most PaaS services) was being built to assume, rather than accommodate as a legacy alternative.
Microsoft's own migration guidance noted that by the time of the IaaS VM retirement announcement, approximately 90% of IaaS VMs on Azure were already running on Azure Resource Manager. The retirement dates formalized an transition that had, for most of Azure's customer base, already substantially happened — which is part of why the final retirement in August 2024 affected a comparatively small, often overlooked population of long-lived subscriptions.
Because retirement completed in 2024, self-service classic-to-ARM migration tooling for most resource types is no longer operable — the classic resource provider endpoints it depended on are disabled. If you're managing a subscription that's existed since before 2024 and have never audited it, these steps identify whether anything classic remains and what to do if it does.
Check the Azure Advisor Service Retirement workbook
In the Azure portal, open Advisor → Workbooks → Service Retirement. Set the Subscription, Resource Group, and Location filters to All, then review the listed resources. This workbook is Microsoft's own tool for surfacing resources scheduled for or affected by retirement, and it's the fastest way to get a definitive list rather than manually hunting.
List resources filtered by classic resource type prefixes
Run
az resource list --query "[?contains(type, 'Classic')]" -o tableagainst each subscription. Classic resource types consistently include "Classic" in their provider namespace — Microsoft.ClassicStorage, Microsoft.ClassicCompute, Microsoft.ClassicNetwork — making this a reliable, scriptable check across every subscription in a tenant.Check storage accounts by their Type column specifically
In the portal, browse to Storage accounts and inspect the Type column for each. An account showing microsoft.classicstorage/storageaccounts is a classic account — distinct from, and requiring different handling than, an ARM-native Microsoft.Storage/storageAccounts resource.
If you find classic remnants, open a support request rather than attempting self-service migration
Because the classic resource provider endpoints were disabled on August 31, 2024, the self-service migration tooling documented for years (validate/prepare/commit workflows via PowerShell or CLI) generally no longer functions against live classic resources for most resource types. If you discover classic remnants — most commonly leftover classic storage accounts with data, or classic virtual network references — open an Azure support request rather than assuming historical migration documentation is still directly actionable; Microsoft support can advise on current options for the specific resource type and its retirement state.
Audit for classic references in older automation, not just live resources
Beyond live classic resources, check older PowerShell scripts, Runbooks, or CI/CD pipelines for calls to classic cmdlets (anything with Azure module prefix rather than Az, or explicit Service Management API calls) — these will fail outright now that the endpoints are gone, and it's better to find and retire this dead automation deliberately than to discover it during an unrelated incident when a scheduled job silently starts failing.
Per Microsoft's own retirement communications for classic storage specifically, data within classic storage accounts was preserved through the transition — accounts were migrated to Resource Manager on a rolling schedule rather than having their data destroyed at the retirement date. If you're investigating an old subscription and expecting data loss from the 2024 retirement, that's usually not what happened; the more common outcome is a dual listing (a classic-looking entry and its ARM-migrated counterpart) or a fully-transitioned ARM resource that no longer shows any classic characteristics at all.
Key Takeaways
Frequently Asked Questions
Related FAVRITE Articles
- RBAC for Azure Files: Least-Privilege Access Patterns
- Purging the Keys: Migrating Azure OpenAI Applications to Managed Identities and RBAC
- Top 100 Azure Cloud Engineer Interview Questions
- Azure Certification Resources