# terraform-provider-azurerm: the Terraform provider for Azure Resource Manager

> It is the HashiCorp-maintained provider that maps Azure Resource Manager resources onto Terraform's declarative model. This article covers how it authenticates, how to run a first resource group and virtual network, and where it stops being the right tool.

**hashicorp/terraform-provider-azurerm** — Terraform provider for Azure Resource Manager

- Repository: https://github.com/hashicorp/terraform-provider-azurerm
- Website: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
- Stars: 4,973 · Forks: 5,061
- Language: Go
- License: MPL-2.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/hashicorp-terraform-provider-azurerm

## The gap terraform-provider-azurerm fills

Azure Resource Manager is an HTTP API. Every resource group, virtual network and storage account is a REST call, and the API expects you to sequence those calls, poll for completion and reconcile drift yourself. terraform-provider-azurerm is the translation layer that turns those calls into Terraform resources, so the same plan/apply cycle that works for AWS or GCP also works against an Azure subscription. The README states the scope plainly: the provider "allows managing resources within Azure Resource Manager".

That scope explains the audience. It is for platform and infrastructure engineers who already run Terraform and now need Azure in the same state file, and for teams that want Azure changes to go through review rather than through portal clicks. It is not a general Azure SDK, and it is not a replacement for the Azure CLI when you are doing one-off investigation. The provider's job is to hold a declared state and make Azure match it.

## How the provider maps ARM onto Terraform

The repository is a Go program that implements the Terraform plugin protocol. The go.mod file shows the shape of the dependency graph: the provider pulls in the legacy Azure SDK for Go (github.com/Azure/azure-sdk-for-go) alongside the newer HashiCorp-maintained go-azure-sdk modules split into data-plane, resource-manager and sdk. It also depends on both terraform-plugin-sdk/v2 and terraform-plugin-framework, plus terraform-plugin-mux. That mux dependency is the interesting part. It means the provider is running two plugin frameworks side by side, which is how a codebase of this age migrates resource by resource without freezing new development.

Data flow is the standard Terraform loop. Terraform Core reads your configuration, calls the provider over gRPC, the provider converts the resource block into ARM REST calls, and the resulting ARM identifiers and properties are written into state. On the next plan, the provider reads the current ARM representation and diffs it against state. Because that diff is computed from ARM's own view of the resource, properties Azure fills in automatically (IDs, provisioning state, generated endpoints) end up in state rather than in your configuration.

The features block in the provider configuration is a behaviour switch, not a resource switch. The README links to a dedicated guide for it and describes it as allowing "changing the behaviour of the Azure Provider". Some defaults that would be destructive, such as purge-on-destroy behaviour for certain services, are governed there rather than on the individual resource. Treat that block as part of your provider contract: changing it can change what apply does.

## Installing the provider and creating a resource group

There is no standalone installer. Terraform fetches the provider from the registry when you run terraform init, and the README's usage example pins the version in a required_providers block. The example below is the README's own configuration, trimmed to the provider block and the first resource.

```hcl
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=5.0.0"
    }
  }
}

provider "azurerm" {
  features {}
}
```

After writing that into a .tf file, run terraform init. Terraform downloads the provider binary and writes a lock file. The README recommends using the latest version of Terraform Core when running version 5.0 of the provider.

Authentication is the part that trips people up. The README says the provider "supports authenticating using via the Azure CLI, a Managed Identity and a Service Principal", and points at the registry documentation for the details. For a local run, an authenticated az login session is usually the shortest path. For CI, a service principal or a managed identity on the runner is the normal choice; the README does not spell out the environment variable names, so read the authentication section of the registry docs rather than guessing.

The second half of the README example adds a resource group and a virtual network inside it, and shows the referencing style the provider relies on.

```hcl
resource "azurerm_resource_group" "example" {
  name     = "example-resources"
  location = "West Europe"
}

resource "azurerm_virtual_network" "example" {
  name                = "example-network"
  resource_group_name = azurerm_resource_group.example.name
  location            = azurerm_resource_group.example.location
  address_space       = ["10.0.0.0/16"]
}
```

Run terraform plan and you should see two resources to add. Note that the virtual network does not repeat the location string; it reads azurerm_resource_group.example.location. That implicit dependency is what makes Terraform create the group first and destroy it last. The README also points at the ./examples folder in the repository, which contains per-service directories such as examples/app-service, examples/cosmos-db and examples/container-registry for fuller configurations.

## Where terraform-provider-azurerm is the wrong tool

Coverage is not uniform, and that is the main practical limit. The provider is a large hand-written mapping over ARM, and the repository layout reflects that: internal/ holds the resource implementations, and the CHANGELOG files are split by major version (CHANGELOG-v0.md through CHANGELOG-v4.md, plus the current CHANGELOG.md). Resource types arrive over time. If a newly announced Azure service is not in the registry documentation for the provider, the provider cannot manage it, and no amount of configuration will change that.

The second limit is the features block. Because it changes provider behaviour globally, a provider configuration that was safe for one team's estate may not be safe for another's. Two workspaces pointing at the same subscription with different features blocks can disagree about what apply does. That is a configuration-management problem the provider does not solve for you.

The third is state. This provider writes ARM identifiers and computed properties into Terraform state, and state is the source of truth for every subsequent plan. Importing existing Azure resources into the provider is a manual, resource-by-resource exercise; the README does not describe a bulk import path. If your estate was built by hand over years, the migration cost sits in that import work, not in writing the HCL.

## AzureRM against AzAPI, and against the CLI

The most direct alternative for the same job is the AzAPI provider, which is maintained by Microsoft rather than HashiCorp. The difference is the level of abstraction. AzureRM exposes curated resource types with named arguments, validation and defaults, so azurerm_virtual_network has an address_space field and the provider knows what to send. AzAPI exposes the ARM API surface more directly, which means a resource that AzureRM has not yet modelled is still reachable, at the cost of writing the request body yourself and losing the provider's argument-level validation. Teams that need a brand-new Azure feature before AzureRM ships it tend to reach for AzAPI for that one resource and keep the rest in AzureRM.

The other alternative is not a provider at all. The Azure CLI is better for exploration, one-off changes and debugging what ARM actually returns. It is worse for anything you want to review, repeat or roll back, because there is no plan step and no state file. Using the CLI to inspect a resource and then encoding the result in AzureRM configuration is a reasonable division of labour; using the CLI as the deployment mechanism for a long-lived environment is not.

## Release cadence, licence and upgrade cost

The provider releases frequently. The recent release list shows v5.6.0 on 2026-09-17, v5.5.0 on 2026-09-10 and v5.4.0 on 2026-09-03, roughly weekly minor versions, and the last push to the repository was on 2026-09-22. This is an actively developed codebase, and the version pinning in the README example (version = "=5.0.0") is there for a reason: an unpinned provider will move under you between runs. Pin it, and upgrade deliberately.

The upgrade cost is real but bounded. The repository keeps a .changelog directory and separate CHANGELOG files per major version, which is where breaking changes are recorded. Major versions are the ones that require edits to your configuration; minor versions within a major line are where new resources and fixes land. Because the provider is a single binary shared by every resource in a workspace, you cannot upgrade one resource type in isolation. A provider bump is an all-or-nothing change for the configuration that references it.

The licence is MPL-2.0, a file-level copyleft licence. You can use the provider and build on it; if you modify the provider's own source files and distribute them, those modified files carry the licence obligations. This is not legal advice, and the LICENSE file in the repository is the authoritative text. For most users the provider is consumed as a downloaded binary and the licence has no practical effect on their own Terraform configurations.

## Conclusion

Adopt terraform-provider-azurerm when your Azure estate is mostly stable, mainstream services and you want one plan/apply workflow over resource groups, networking, storage and the rest. It is the wrong tool when you need a resource type that the provider has not yet shipped, or when you are managing data-plane objects that ARM never exposed; the AzureRM README points at the Azure CLI, Managed Identity and Service Principal as its authentication paths, so verify that one of those works in your environment before you build a pipeline around it. Check the registry documentation for the specific resource types you plan to use, and check whether the feature you depend on sits behind the features block, because that block changes provider behaviour rather than resource behaviour.

## FAQ

### What is the Terraform resource provider for Microsoft Azure?

It is terraform-provider-azurerm, which the README describes as allowing management of resources within Azure Resource Manager. You declare Azure resources in HCL, and the provider translates them into ARM calls during plan and apply.

### What are the key differences between AzureRM and AzAPI Terraform providers?

AzureRM exposes curated resource types with named arguments and validation, while AzAPI exposes the ARM API surface more directly. That makes AzAPI the fallback when a resource type has not yet been modelled in AzureRM, at the cost of writing the request body yourself.

### How to install provider in Terraform for Azure?

There is no separate installer. You declare hashicorp/azurerm in a required_providers block with a version constraint, then run terraform init, which downloads the provider and writes a lock file.

## Sources

- [hashicorp/terraform-provider-azurerm on GitHub](https://github.com/hashicorp/terraform-provider-azurerm)
- [License: MPL-2.0](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/LICENSE)
- [Project website](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
- [README](https://github.com/hashicorp/terraform-provider-azurerm/blob/main/README.md)
- [Releases](https://github.com/hashicorp/terraform-provider-azurerm/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hashicorp-terraform-provider-azurerm
