Azure Key Vault Naming Conventions: CAF Rules and Soft-Delete Gotchas
CAF compliant naming for Azure Key Vault, including the 24-character limit, globally unique names, soft-delete name reservation, and Terraform/Bicep examples.
Key Vault names use the CAF prefix
kv, for examplekv-payments-prod-eus-001. They must be 3 to 24 characters, alphanumerics and hyphens, start with a letter, and be globally unique. Deleting a vault reserves its name for 90 days under soft-delete, so choose names that avoid collisions.
Azure Key Vault has two naming quirks that catch teams out: the 24-character maximum, and soft-delete name reservation. A Key Vault you delete stays reserved under that name for 90 days, even across subscriptions. Get the naming right upfront, because recovering from a collision on a deleted vault is surprisingly painful.
The constraints
| Rule | Detail |
|---|---|
| CAF prefix | kv |
| Min length | 3 characters |
| Max length | 24 characters |
| Allowed characters | Alphanumerics and hyphens |
| Must start with | A letter |
| Must end with | A letter or digit |
| Scope of uniqueness | Global (within Azure public cloud) |
| Soft-delete reservation | 90 days after deletion |
CAF naming pattern
kv-{workload}-{environment}-{region}-{instance}
Examples:
| Workload | Environment | Region | Key Vault name |
|---|---|---|---|
| payments | prod | eus | kv-payments-prod-eus |
| hrportal | dev | weu | kv-hrportal-dev-weu |
| shared | prod | eus | kv-shared-prod-eus-001 |
| infra | stg | uks | kv-infra-stg-uks-001 |
Note that kv-payments-prod-eus is already 20 characters, you have 4 characters left for an instance number before hitting the 24-character ceiling. For longer workload names, abbreviate:
kv-pmts-prod-eus-001 ← "pmts" for payments (22 chars)
kv-hrp-prod-eus-001 ← "hrp" for hrportal (19 chars)
The soft-delete gotcha
Since Azure Key Vault 2020, soft-delete is mandatory and cannot be disabled. When you delete a Key Vault, its name is reserved for 90 days in a “soft-deleted” state, even if you move to a different subscription or even a different Azure AD tenant in the same cloud.
This creates a problem in CI/CD pipelines and Terraform workflows that create and destroy environments frequently. If a Key Vault named kv-payments-dev-eus-001 is destroyed in a teardown, you can’t create a new one with the same name for 90 days.
Solutions
Option 1, Purge on delete (Terraform):
resource "azurerm_key_vault" "main" {
name = "kv-payments-dev-eus-001"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
soft_delete_retention_days = 7 # minimum allowed
purge_protection_enabled = false # allow hard delete
}
With purge_protection_enabled = false and a short retention, you can manually purge the vault after deletion and immediately reuse the name. Never disable purge protection in production.
Option 2, Include a timestamp or build ID in the name:
variable "instance" { default = "001" } # bump this for each teardown cycle
resource "azurerm_key_vault" "main" {
name = "kv-payments-dev-eus-${var.instance}"
}
Option 3, Don’t destroy dev Key Vaults; rotate secrets instead. If the vault is cheap to keep running (it is, ~$0/month at low usage), leave it and rotate the secrets rather than deleting the vault.
Purging a soft-deleted Key Vault
If you’re blocked by a soft-deleted vault name, purge it from the CLI:
# List soft-deleted vaults
az keyvault list-deleted --resource-type vault
# Purge a specific vault (irreversible)
az keyvault purge --name kv-payments-dev-eus-001 --location eastus
Or from PowerShell:
Get-AzKeyVault -InRemovedState
Remove-AzKeyVault -VaultName "kv-payments-dev-eus-001" -Location "eastus" -InRemovedState -Force
Managed HSM naming
Azure Dedicated HSM and Managed HSM have their own resource type:
| Resource | CAF prefix | Max length | Hyphens |
|---|---|---|---|
| Key Vault (standard/premium) | kv | 24 | Yes |
| Managed HSM | kvmhsm | 24 | Yes |
kvmhsm-payments-prod-eus-001
Naming in Terraform
variable "workload" { default = "payments" }
variable "environment" { default = "prod" }
variable "region" { default = "eus" }
resource "azurerm_resource_group" "main" {
name = "rg-${var.workload}-${var.environment}-${var.region}-001"
location = "eastus"
}
data "azurerm_client_config" "current" {}
resource "azurerm_key_vault" "main" {
name = "kv-${var.workload}-${var.environment}-${var.region}-001"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
tenant_id = data.azurerm_client_config.current.tenant_id
sku_name = "standard"
soft_delete_retention_days = 90
purge_protection_enabled = true # required for production
tags = {
environment = var.environment
workload = var.workload
}
}
Naming in Bicep
param workload string = 'payments'
param environment string = 'prod'
param region string = 'eus'
var kvName = take('kv-${workload}-${environment}-${region}-001', 24)
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
name: kvName
location: resourceGroup().location
properties: {
sku: {
family: 'A'
name: 'standard'
}
tenantId: subscription().tenantId
enableSoftDelete: true
softDeleteRetentionInDays: 90
enablePurgeProtection: true
}
}
The take() function truncates to 24 characters if the name would exceed the limit, safer than letting the deployment fail at runtime.
Summary
- Pattern:
kv-{workload}-{environment}-{region}-{instance}, 24-character max, hyphens allowed - Names are globally unique across all of Azure; plan accordingly
- Soft-delete reserves your vault name for 90 days after deletion, critical for ephemeral environments
- Disable purge protection only in dev/test; always enable it in production
- Use
take()in Bicep orsubstr()in Terraform to guard against truncation at the 24-char limit
Use AzureNamer to generate compliant Key Vault names in seconds.
Keep reading
Azure API Management Naming Conventions: Service, APIs, and Products
CAF naming for Azure API Management. The service is a globally unique azure-api.net endpoint (1 to 50 chars); APIs, products, backends, and named values inside are function-named. Patterns and examples.
Read →Azure Service Bus Naming Conventions: Namespaces, Queues, and Topics
CAF naming for Azure Service Bus. The namespace is a globally unique servicebus.windows.net endpoint (6 to 50 chars); queues, topics, and subscriptions inside are relaxed. Patterns and examples.
Read →Azure Container Registry Naming: Rules, Limits, and CAF Patterns
Azure Container Registry name requirements: 5 to 50 characters, lowercase alphanumeric only, no hyphens, globally unique. The CAF pattern, examples, and Terraform and Bicep.
Read →Try AzureNamer
Generate CAF compliant names for all 200+ Azure resource types, free, no login required.
Open the Generator →