Azure Verified Modules (AVM) for Terraform
What Azure Verified Modules are, why they beat hand-rolled resource blocks, and how to find and consume them in Terraform.
While building out my Central US vWAN landing zone extension, I needed a vWAN hub, Azure Firewall Premium, a VPN Gateway, and a DNS Private Resolver. I could have hand-rolled azurerm resources for each one. Instead I used Azure Verified Modules, and that is what got me using AVM in the first place.
What is AVM?
Azure Verified Modules is a Microsoft-driven initiative, with community contributions, to standardize what a good Infrastructure-as-Code module looks like. It covers both Bicep and Terraform. Modules that meet the spec are classified as AVM and published to each language’s registry: the Terraform Registry for Terraform, and the Bicep public registry or template specs for Bicep.
Module Types
AVM modules come in three types:
- Resource modules deploy one resource plus its child and extension resources. An example is
avm-res-keyvault-vault. - Pattern modules compose multiple resources into a full architecture, such as a landing zone or an AKS pattern.
- Utility modules are helpers, like naming convention or region generation. They are not actual Azure resources.
Why Use Them?
- Sane defaults. Default configurations are aligned with the Well Architected Framework.
- Official support. The modules are owned and supported by Microsoft. Support goes through GitHub issues on the module repo or the AVM repo.
- Predictable upgrades. Modules are versioned with semver, so you know what an upgrade means before you take it.
- Less boilerplate. You stop writing the same resource blocks over and over.
How to Find a Module
Search for “avm” on registry.terraform.io, or browse the AVM Terraform module indexes.
One caution: some modules have “avm” in the name but are not real AVMs. Check for the Partner/official tag on the registry page to tell the difference.
How to Use a Module in Terraform
-
Open the module’s page on the Terraform Registry and find the “Provision Instructions” box. It contains the module source string. For resource modules the pattern is
Azure/avm-res-<service>-<resource>/azure. For Key Vault, that looks like:source = "Azure/avm-res-keyvault-vault/azure" -
Pin a version constraint alongside the source so upgrades happen when you choose.
-
Set
enable_telemetryexplicitly. Every AVM Terraform module exposes this input astrueorfalse, and it must be set. -
Open the Examples tab on the registry page. Each module ships ready-made example blocks, for instance a
create-keyexample for Key Vault. Copy one and adapt it. This is faster than reading the Inputs tab and writing every input from scratch.
Put together, the shape of a module block looks like this. Add a version constraint from the registry page and copy the remaining inputs from the examples for your module:
module "keyvault" {
source = "Azure/avm-res-keyvault-vault/azure"
enable_telemetry = true
# remaining inputs copied from the Examples tab
}
My Usage
In the vWAN landing zone extension, each of these components came from an AVM resource module rather than hand-written azurerm resources:
- vWAN hub
- Azure Firewall Premium
- VPN Gateway
- DNS Private Resolver
Starting from the registry examples and adjusting inputs for my environment kept each component consistent, and the semver versioning means I can see what changes before bumping a module.