Terraform AzureRM Provider 5.0: Breaking Changes and Upgrade Guide

Terraform AzureRM Provider 5.0: Breaking Changes and Upgrade Guide

HashiCorp shipped AzureRM provider 5.0 on July 27, 2026 (a 5.0.1 patch followed shortly after), and it's not a routine version bump. If your Terraform configs have been running fine against 4.x for months and you run terraform init -upgrade without reading anything first, there's a good chance your next terraform apply fails on a Resource Provider that quietly stopped registering itself. This walks through what actually changed and how to upgrade without breaking a pipeline.

Why this is a bigger deal than a normal major version

Provider major versions usually mean a handful of renamed arguments and a deprecation cycle you've already been warned about. AzureRM 5.0 does that too, but it also changes two behaviors that most teams never explicitly configured because the defaults just worked: automatic Azure Resource Provider (RP) registration, and pre-flight validation of locations and RPs before Azure ever sees your request. Both flip from "on by default" to "off by default." If your subscription's RPs were only ever registered because the provider did it silently on every terraform init/apply, 5.0 is the first time anyone has to think about it.

Breaking change 1: Resource Provider registration is now opt-in

Old behavior (4.x): resource_provider_registrations defaulted to "legacy", which had the provider register roughly 60 Azure Resource Providers on startup โ€” regardless of whether your config used them. This was slow, and it silently failed (or required elevated permissions) for anyone whose subscription access didn't include Microsoft.Authorization/*/register/action at that scope.

New behavior (5.0): the default is resource_provider_registrations = "none". Nothing gets auto-registered. If your config references a resource type under an RP that was never explicitly registered on the subscription, terraform apply fails with an RP-not-registered error โ€” not terraform plan, because plan doesn't touch Azure's control plane the same way.

Fix it explicitly rather than reaching for the old default:

1provider "azurerm" {
2  resource_providers_to_register = [
3    "Microsoft.Compute",
4    "Microsoft.Network",
5    "Microsoft.Storage",
6  ]
7  features {}
8}

This registers only what your config actually needs, which is also the more correct behavior for least-privilege service principals. If you need to buy time and just want 4.x behavior back while you sort out the real list:

1provider "azurerm" {
2  resource_provider_registrations = "legacy"
3  features {}
4}

Treat that as a temporary bridge, not the fix โ€” it re-introduces the same startup cost and permission requirement 5.0 was designed to remove.

Breaking change 2: enhanced validation moved and flipped default

Old behavior: enhanced_validation lived at the provider's top level and defaulted to validating locations and Resource Providers before terraform plan would even show you a diff โ€” catching typos in a location argument or a not-yet-registered RP early.

New behavior: the block moved inside features, and both location and RP validation now default to disabled. The ARM_PROVIDER_ENHANCED_VALIDATION environment variable is gone.

If you relied on that early-catch behavior (most teams did, without realizing it), re-enable it explicitly:

1provider "azurerm" {
2  features {
3    enhanced_validation {
4      locations          = true
5      resource_providers = true
6    }
7  }
8}

There's also a new opt-in preflight validation mode that checks resource-level constraints (not just locations/RPs) before apply:

1provider "azurerm" {
2  features {
3    enhanced_validation {
4      preflight_enabled           = true
5      preflight_location_fallback = "eastus2"
6    }
7  }
8}

Practical effect: without re-enabling validation, a typo'd region or an unregistered RP now surfaces at apply time instead of plan time โ€” worse for CI pipelines that gate on plan output looking clean before promoting to apply.

Breaking change 3: 40+ deprecated resources are gone, not just deprecated

5.0 removes resources that had been deprecated across several 4.x releases. If you never migrated off them, terraform init or plan will now fail outright instead of printing a warning. The ones most teams actually hit:

RemovedUse instead
azurerm_app_serviceazurerm_linux_web_app / azurerm_windows_web_app
azurerm_app_service_planazurerm_service_plan
azurerm_app_service_slotazurerm_linux_web_app_slot / azurerm_windows_web_app_slot
azurerm_function_appOS-specific azurerm_linux_function_app / azurerm_windows_function_app
azurerm_postgresql_server (legacy family)azurerm_postgresql_flexible_server
azurerm_hpc_cache (all variants)retired โ€” no direct replacement, redesign onto current storage/compute

Property renames follow the same enable_x โ†’ x_enabled pattern the provider has been converging on for a while โ€” e.g. enable_http2 is gone in favor of http2_enabled, local_authentication_disabled in favor of local_authentication_enabled. TLS minimum version arguments also stop accepting 1.0/1.1 outright.

Step-by-step upgrade process

  1. Pin the provider version explicitly before touching anything:
    1terraform {
    2  required_providers {
    3    azurerm = {
    4      source  = "hashicorp/azurerm"
    5      version = "~> 5.0"
    6    }
    7  }
    8}
    
  2. Grep your configs and modules for removed resources (the table above covers the common ones; check the full upgrade guide for anything niche like azurerm_maps_creator).
  3. Decide your RP registration strategy โ€” explicit resource_providers_to_register list (recommended) vs. resource_provider_registrations = "legacy" as a stopgap.
  4. Decide whether to re-enable enhanced/preflight validation โ€” if your CI gates on plan, you probably want it back on.
  5. Run terraform init -upgrade and terraform plan in a non-prod workspace first. Read the plan output line by line โ€” a clean plan with 5.0 doesn't guarantee a clean apply if RP registration is the gap, since plan doesn't hit the same code path as apply for that check.
  6. Roll out module-by-module if you have a large monorepo, not all at once โ€” a single removed resource in a shared module can block every consumer of that module simultaneously.

Best practices

  • Register RPs explicitly per environment, not blanket per organization โ€” a dev subscription and a prod subscription rarely need the same RP set, and least-privilege service principals should only get registration rights for what they use.
  • Re-enable enhanced_validation in CI even if you skip it locally โ€” catching a bad location string at plan review time beats catching it mid-apply in a pipeline.
  • Don't leave resource_provider_registrations = "legacy" in place long-term โ€” it's a compatibility shim, and it reintroduces the startup latency and broad permission requirement 5.0 removed for a reason.
  • Audit modules you don't own (internal shared modules, third-party registry modules) separately โ€” they're the most common place a removed resource hides from a surface-level grep of your own root config.

Common mistakes to avoid

  • Upgrading the provider and applying straight to production. The RP registration failure mode specifically doesn't show up until apply, so a "clean plan" is not sufficient evidence of a safe upgrade.
  • Assuming resource_provider_registrations = "legacy" is the permanent fix. It gets you back to 4.x behavior, including the permission requirements and startup delay that were the actual reason this changed.
  • Missing renamed properties in modules pulled from the public registry. Pin module versions too, not just the provider โ€” an unpinned community module can silently start using 5.0-only syntax underneath you.
  • Skipping the non-prod dry run because "it's just a provider bump." This release specifically breaks the plan/apply parity teams rely on for safety.

Troubleshooting

If terraform apply fails with a Resource Provider not registered error after upgrading:

  1. Confirm the RP isn't in your resource_providers_to_register list โ€” add it, or check az provider list --query "[?registrationState=='NotRegistered']" against what your config actually needs.
  2. Confirm the identity Terraform runs as has Microsoft.Authorization/*/register/action at the subscription (or management group) scope โ€” without it, even an explicit registration list will fail.
  3. If a plan looked clean but apply still fails, that's the expected behavior gap โ€” validation is off by default now, so re-enable enhanced_validation to catch this earlier next time.

FAQ

Do I have to migrate off resource_provider_registrations = "legacy" right now? No โ€” it's a supported value, not a removed one. It's a stopgap, not a deprecated setting, but it does bring back the original startup cost and broad permission requirement.

Will terraform plan catch a missing Resource Provider registration? Not by default in 5.0. That check now happens at apply unless you explicitly re-enable enhanced_validation.resource_providers = true.

Does this affect OpenTofu users the same way? The AzureRM provider is shared across Terraform and OpenTofu since it's a standard Terraform Registry provider, so yes โ€” the same breaking changes apply if you pull hashicorp/azurerm 5.x into an OpenTofu config.

Is there a way to see exactly which resources my config uses that were removed? Run terraform init first โ€” it fails fast on any resource type the provider schema no longer recognizes, before you even get to plan.

What if I'm not ready to upgrade at all? Pin to the last 4.x release (~> 4.0) in required_providers and stay there deliberately โ€” just don't let an unpinned >= 4.0 constraint silently pull 5.x into a build.

Key takeaways

Area4.x5.0
Resource Provider registrationAuto (~60 RPs) via legacy defaultOpt-in only, explicit list recommended
Enhanced validationOn by default, provider-levelOff by default, moved inside features
Failure surfaces atMostly planRP issues now surface at apply
Deprecated resourcesWarned, still worked40+ removed outright
Property namingMixed enable_x / x_enabledStandardized on x_enabled

Further Reading