Stop wasting time manually crafting Azure resource names and eliminate naming inconsistencies across your infrastructure. This Terraform module automates your entire Azure naming convention, ensuring every resource—from resource groups to storage accounts to key vaults—follows your organizational standards automatically.
What you get:
- Instant productivity: Define your convention once, apply it everywhere—across all 70+ Azure resource types and Azure Regions!
- Zero errors: No more typos, forgotten abbreviations, or inconsistent patterns
- Multi-region made simple: Deploy to multiple Azure Regions with automatic location-aware naming
- Multi-Provider flexibility: Supports both the
azurermandazapiAzure providers for Terraform for maximum flexibility of adhering to your naming convention - Team alignment: Everyone on your team uses the same naming standard without thinking about it
- Proven foundation: This module is built on and extends Microsoft's official Azure/naming/azurerm module
Transform hours of naming decisions into seconds with a consistent, location‑aware, environment‑aware Microsoft Azure resource naming convention.
module "azure_primary" {
source = "Build5Nines/naming/azure"
organization = "b59"
environment = "prod"
location = "East US" # or "eastus"
}
resource "azurerm_resource_group" "main" {
name = module.azure_primary.resources.resource_group.name
location = module.azure_primary.location
}Resulting resource group name pattern (example):
rg-b59-eus-prod
(rg is applied internally by the upstream module as the slug for a resource group.)
This naming pattern enables the use of this module to more easily adhere to a defined Azure resource naming convention for multiple Azure resources. Here's an example of using this to set the prefix of the Azure resource names using the defined naming convention while also naming them according to the specific workload and using the correct Azure resource abbreviation:
resource "azurerm_storage_account" "files" {
name = "${module.azure_primary.resources.storage_account.name}files"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
account_tier = "Standard"
account_replication_type = "GRS"
}
resource "azurerm_sql_server" "sql_data" {
name = "${module.azure_primary.resources.sql_server.name}-data"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
version = "12.0"
administrator_login = "dataadministrator"
administrator_login_password = "b59isawesome"
}Resulting resources will be named (example):
Azure Storage Account = stb59eusprodfiles
Azure SQL Server = sql-b59-eus-prod-data
If you're looking for some more practical example usages of this module, check out the following:
- Multi-Region Deployment with Multiple Workloads in Single Terraform Project: This is an example Terraform project demonstrating how to use the
Build5Nines/naming/azuremodule to deploy a multi-region deployment across 2 Azure Regions (Primary and Secondary Region Pair) that includes Azure resources for multiple workloads within a single Terraform project.
- Eliminate naming inconsistencies across your Azure infrastructure with a single, reusable module.
- Save time and reduce errors by automating complex naming conventions instead of manually crafting names.
- Manage multi-region architectures more easily with built-in region pairing and location-aware naming.
- Maintain compliance with organizational standards through consistent naming patterns across all environments.
- Access 70+ Azure resource types with proper abbreviations and constraints—all from one unified interface.
- Scale your infrastructure confidently knowing every resource follows your defined naming convention.
The resources output is an entire instantiated module object from Azure/naming/azurerm, not just a string. This means that the resources output has properties for each Azure Resource type. Each resource (e.g. .resources.app_service) is an object with additional properties for that Azure Resource type:
| Property | Description |
|---|---|
name |
Generated name with your suffix applied. |
name_unique |
Same as name but with additional random characters for uniqueness (when supported). |
slug |
Short identifier segment for the resource type (e.g. rg, sa, kv). |
min_length |
Minimum allowed length. |
max_length |
Maximum allowed length. |
scope |
Uniqueness scope (resourcegroup, global, etc.). |
dashes |
Whether dashes are allowed. |
regex |
Validation regex (Terraform compatible). |
Example usages:
# Storage Account
resource "azurerm_storage_account" "sa" {
name = module.azure_primary.resources.storage_account.name
resource_group_name = azurerm_resource_group.main.name
location = module.azure_primary.location
account_tier = "Standard"
account_replication_type = "LRS"
}
# Unique variation (if collision risk)
resource "azurerm_key_vault" "kv" {
name = module.azure_primary.resources.key_vault.name_unique
resource_group_name = azurerm_resource_group.main.name
location = module.azure_primary.location
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
}location_secondary exposes the paired (or canonicalized) region derived from data/region_pair.json. Use it to instantiate a second module instance for DR / HA scenarios:
module "azure_secondary" {
source = "Build5Nines/naming/azure"
organization = module.azure_primary.organization
environment = module.azure_primary.environment
location = module.azure_primary.location_secondary
}The default suffix is equivalent to the pattern array:
name_suffix = ["{org}", "{loc}", "{env}"]You can rearrange or add static parts:
module "azure_primary" {
source = "Build5Nines/naming/azure"
organization = "b59"
environment = "dev"
location = "westeurope"
name_suffix = ["{org}", "{env}", "{loc}"] # b59-dev-weu
}The default prefix is empty, so if you want to use the prefix patter instead of the suffix pattern you'll need to set the input variables for what you need.
Here's an example of using a Prefix Naming Pattern (via name_prefix):
module "azure_primary" {
source = "Build5Nines/naming/azure"
organization = "b59"
environment = "prod"
location = "westus"
name_prefix = ["{org}", "{env}", "{loc}"] # b59-dev-wus
name_suffix = []
}
resource "azurerm_storage_account" "sa" {
name = module.azure_primary.resources.storage_account.name
resource_group_name = azurerm_resource_group.main.name
location = module.azure_primary.location
account_tier = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_sql_server" "sql_data" {
name = "${module.azure_primary.resources.sql_server.name}-data"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
version = "12.0"
administrator_login = "dataadministrator"
administrator_login_password = "b59isawesome"
}In this example of using a Prefix Naming Pattern, the Azure resource names will be set to:
Azure Storage Account = b59devwussa
Azure SQL Server = b59-dev-wus-sql-data
Override region abbreviations:
module "azure_primary" {
source = "Build5Nines/naming/azure"
organization = "b59"
environment = "prod"
location = "East US"
location_abbreviations = {
eastus = "east" # overrides default "eus"
westus = "west"
}
}Override the secondary location by setting a custom secondary region on the primary module:
module "azure_primary" {
source = "Build5Nines/naming/azure"
organization = "b59"
environment = "prod"
location = "East US"
location_secondary = "North Central US # or "northcentralus"
}
# Now module.azure_primary.location_secondary == "North Central US"By default, the module will lookup the Microsoft Region Pair to return for the location_secondary output from the module. By setting the location_secondary explicitly, you can override this behavior by setting the secondary location needed for your own disaster recovery plans.
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
organization |
Organization / business unit segment. | string | "" | yes* |
environment |
Environment segment (dev, test, prod, etc.). | string | "" | yes* |
location |
Azure region (display or programmatic). | string | n/a | yes |
name_prefix |
Ordered list of pattern tokens / literals forming the prefix. Tokens: {org}, {loc}, {env}. |
list(string) | `[] | no |
name_suffix |
Ordered list of pattern tokens / literals forming the suffix. Tokens: {org}, {loc}, {env}. |
list(string) | ["{org}", "{loc}", "{env}"] |
no |
location_abbreviations |
Map of region -> abbreviation overrides (display or programmatic keys). | map(string) | {} |
no |
location_secondary |
Optional override for the secondary region. When set (non-empty), the location_secondary output will equal this value instead of the computed Microsoft regional pair. |
string | "" | no |
unique_include_numbers |
Include numbers in the unique suffix generation. | bool | true |
no |
unique_length |
Max length of the uniqueness suffix to be added | number | 4 |
no |
unique_seed |
Custom value for the random characters to be used | string | "" | no |
organization / environment default to empty strings; supplying them is strongly recommended for meaningful names.
| Name | Description |
|---|---|
base_suffix |
Final joined suffix string (e.g. b59-eus-prod). |
resources |
The full upstream Azure naming module instance (access resource names via resources.<resource>.name). |
organization |
Echo of var.organization. |
environment |
Echo of var.environment. |
location |
Original provided location input. |
location_abbreviation |
Resolved abbreviation (override > JSON > canonical short name). |
location_secondary |
Secondary region. If var.location_secondary is set (non-empty), this output equals that value; otherwise it is the paired/canonicalized region from region_pair.json. |
Example referencing an output:
locals {
rg_name = module.azure_primary.resources.resource_group.name
storage_slug = module.azure_primary.resources.storage_account.slug # "st"
}- Canonicalization:
location_canonical = lower(replace(var.location, " ", "")). - Abbreviations: Merge of JSON defaults + raw overrides + canonicalized override keys.
- Region pairing:
region_pair.jsonmaps both display and programmatic names to a paired region. - Suffix expansion: Each element of
var.name_suffixhas tokens replaced; result list joined into a single string by the upstream module when composing names. - Upstream module call:
module "azure_naming" { source = "Azure/naming/azurerm" suffix = local.name_suffix }
- Use
name_uniquefor resources that require globally unique naming (storage accounts, key vaults, etc.). - Derive secondary region infra with
location_secondary. - Compose additional naming layers by appending static literals in
name_suffix(e.g. add a workload slug{org}-{loc}-{env}-app). - Inspect constraints before naming collisions:
module.azure_primary.resources.storage_account.max_length.
| File | Purpose |
|---|---|
data/region_abbr.json |
Default abbreviations keyed by canonical short region names. |
data/region_pair.json |
Region pairing / canonicalization map (primary -> secondary). |
Additions/changes are simple JSON edits; prefer PRs with minimal diff noise.
This module wraps and extends the Microsoft Azure/naming/azurerm module, adding organizational & regional context consistency while reusing its comprehensive resource naming logic.
module "azure_primary" {
source = "Build5Nines/naming/azure"
organization = "b59"
environment = "prod"
location = "East US"
}
module "azure_secondary" {
source = "Build5Nines/naming/azure"
organization = module.azure_primary.organization
environment = module.azure_primary.environment
location = module.azure_primary.location_secondary
}
resource "azurerm_resource_group" "primary" {
name = module.azure_primary.resources.resource_group.name
location = module.azure_primary.location
}
resource "azurerm_resource_group" "secondary" {
name = module.azure_secondary.resources.resource_group.name
location = module.azure_secondary.location
}| Symptom | Cause | Fix |
|---|---|---|
Validation error for location |
Region not in allow list | Use a supported region or update variables.tf. |
| Unexpected abbreviation | Override not applied | Ensure key matches display or programmatic name; canonical form will also work. |
| Missing paired region | Pair absent in region_pair.json |
Add entry mapping both display & programmatic names. |
Q: Why an array (name_suffix) instead of a single template string?
Allows easier reordering and alignment with upstream module expectations (suffix accepts list).
Q: Why an array (name_prefix) instead of a single template string?
Using an array for name_prefix allows for greater flexibility in ordering and customization. It aligns with the upstream module's expectations, as the prefix can accept a list of tokens, making it easier to manage and modify the naming patterns as needed.
Q: Can I add a workload slug?
Yes, you can add a literal to either the name_prefix or name_suffix as required for your naming convention: ["{org}", "{loc}", "{env}", "api"].
This project is created and maintained by Chris Pietschmann, Microsoft MVP (Azure and Dev Tools), HashiCorp Ambassador, and MCT.