Azure Storage Account Naming Conventions: Rules, Limits, and CAF Patterns
Storage accounts have the strictest naming rules in Azure — 3 to 24 characters, lowercase alphanumeric only, globally unique. Here's how to get it right.
Azure storage accounts have the most restrictive naming rules of any common Azure resource — and the constraints that trip people up most often. No hyphens. No uppercase. Globally unique across all of Azure. Maximum 24 characters. If you’ve ever hit a StorageAccountAlreadyTaken error at 2 AM, this guide is for you.
The constraints
| Rule | Detail |
|---|---|
| Min length | 3 characters |
| Max length | 24 characters |
| Allowed characters | Lowercase letters and numbers only |
| Hyphens | Not allowed |
| Uppercase | Not allowed |
| Scope of uniqueness | Global (across all Azure, all tenants) |
| CAF prefix | st |
These constraints exist because storage account names become part of the DNS hostname: {name}.blob.core.windows.net. DNS hostnames can’t contain hyphens at that position and must be globally unique.
CAF pattern for storage accounts
Because hyphens aren’t allowed, the CAF convention concatenates components rather than separating them:
st{workload}{environment}{region}{instance}
Examples:
| Workload | Environment | Region | Storage account name |
|---|---|---|---|
| payments | prod | eus | stpaymentsprodeus001 |
| hrportal | dev | weu | sthrportaldevweu001 |
| backups | prod | uks | stbackupsproduk001 |
| logs | prod | eus | stlogsprodeus001 |
Notice there’s no separator between components — just concatenation. This is intentional and CAF-recommended.
The 24-character limit in practice
With a 2-character prefix (st) you have 22 characters left for workload + environment + region + instance. This is tight. A few strategies:
Abbreviate the workload
| Full name | Abbreviation |
|---|---|
payments | pay or pmts |
humanresources | hr |
applicationlogs | applogs |
terraformstate | tfstate |
Use shorter environment codes
| Environment | Short code |
|---|---|
prod | p |
dev | d |
staging | s |
test | t |
Use shorter region codes
| Region | Full | Short |
|---|---|---|
| East US | eus | e |
| West US 2 | wus2 | w |
| West Europe | weu | we |
For small environments, using single-character codes is acceptable:
stpayp001 ← payments, production, instance 001
stpaymentspd ← payments, prod, no region (if single-region)
Pick an abbreviation scheme and document it — consistency matters more than any specific choice.
Checking availability
Storage account names must be globally unique before you can create them. Check from the CLI:
az storage account check-name --name stpaymentsprodeus001
Output:
{
"message": null,
"nameAvailable": true,
"reason": null
}
Or from PowerShell:
(Get-AzStorageAccountNameAvailability -Name "stpaymentsprodeus001").NameAvailable
In Terraform, the azurerm_storage_account plan phase will also catch name conflicts, but only at apply time — checking availability beforehand saves a failed deployment.
Naming in IaC
Terraform:
variable "workload" { default = "payments" }
variable "environment" { default = "prod" }
variable "region" { default = "eus" }
locals {
# Remove hyphens, force lowercase, enforce 24-char limit
storage_name = lower(
substr(
replace("st${var.workload}${var.environment}${var.region}001", "-", ""),
0, 24
)
)
}
resource "azurerm_storage_account" "main" {
name = local.storage_name
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
account_tier = "Standard"
account_replication_type = "LRS"
}
Bicep:
param workload string = 'payments'
param environment string = 'prod'
param region string = 'eus'
var storageName = take(
toLower(replace('st${workload}${environment}${region}001', '-', '')),
24
)
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
name: storageName
location: resourceGroup().location
kind: 'StorageV2'
sku: { name: 'Standard_LRS' }
}
The take() function in Bicep (and substr() in Terraform) truncates the name if the concatenated value exceeds 24 characters — safer than letting the deployment fail.
Special storage account types
Azure has several storage-adjacent resource types with their own naming rules:
| Resource type | CAF prefix | Max length | Hyphens |
|---|---|---|---|
| Storage account | st | 24 | No |
| Azure Data Lake Storage Gen2 | dls | 24 | No |
| Azure File Share | share- | 63 | Yes |
| Blob container | (no prefix) | 63 | Yes |
| Queue | (no prefix) | 63 | Yes |
| Table | (no prefix) | 63 | No |
Blob containers, queues, and file shares within a storage account have their own naming rules that are more relaxed — they allow hyphens and are longer. Only the storage account itself has the strict 24-character no-hyphen constraint.
Enforcing storage account naming with Azure Policy
{
"if": {
"allOf": [
{ "field": "type", "equals": "Microsoft.Storage/storageAccounts" },
{ "field": "name", "notMatch": "st*" }
]
},
"then": { "effect": "Deny" }
}
For stricter enforcement matching the full pattern:
{
"if": {
"allOf": [
{ "field": "type", "equals": "Microsoft.Storage/storageAccounts" },
{ "field": "name", "notLike": "st*" }
]
},
"then": { "effect": "Audit" }
}
Summary
- No hyphens, no uppercase, 3–24 characters, globally unique — these are hard constraints, not suggestions
- Concatenate components without separators:
st{workload}{environment}{region}{instance} - Use
take()/substr()in IaC to prevent name truncation errors at deploy time - Check name availability before deployment with
az storage account check-name - Document your abbreviation scheme — consistency across all storage accounts matters more than any specific choice
AzureNamer generates compliant storage account names automatically, respecting the 24-character limit and no-hyphen rule for all 203 Azure resource types.
Try AzureNamer
Generate CAF-compliant names for all 203 Azure resource types — free, no login required.
Open the Generator →