Origin Story
This algorithm was born from frustration. While working as a Systems Engineer managing dozens of Azure subscriptions across multiple clients, I kept running into the same problem: every naming convention eventually broke.
Team leads would create a naming standards document. Usually a spreadsheet mapping abbreviations to environments, regions, and resource types. It worked for the first 10 resources. By resource 50, someone had picked a Storage Account name that was too long. By resource 100, two subscriptions had the same abbreviation. By resource 200, the spreadsheet had three conflicting versions and nobody knew which was current.
I realized the fundamental mistake: everyone was treating naming as a policy problem (write rules, hope people follow them) when it's actually a math problem (derive names deterministically from data that already exists). Azure subscription names are already globally unique. Why not leverage that?
That insight became Front9/Back9: extract the subscription's identity mathematically, then adapt it to each resource type's constraints. No spreadsheets. No lookups. No human judgment required.
The Problem in Detail
Azure resource naming looks simple until you try to standardize it. Each resource type has its own rules:
| Resource | Max Length | Allowed Characters | Scope |
|---|---|---|---|
| Key Vault | 24 | Alphanumeric + dashes | Global |
| Storage Account | 24 | Lowercase + numbers only | Global |
| Virtual Machine | 15 | Alphanumeric + dashes | Resource Group |
| Network Interface | 80 | Alphanumeric + dashes/underscores | Resource Group |
Most organizations solve this with a naming convention document: a lookup table mapping abbreviations to resource types, environments, and regions. These tables work until they don't. Someone picks a name that's too long, or uses uppercase where it's forbidden, or the convention can't accommodate a new subscription.
I saw the pattern others missed: This isn't a naming problem. It's a math problem. If you can extract a unique identity from the subscription name and adapt it to each resource type's constraints, the naming convention generates itself.
For the complete reference with all type codes, purpose codes, PowerShell helpers, Terraform examples, and deployment checklists, see the Full Naming Convention Reference.
The Algorithm
Front9/Back9 extracts the first 9 and last 9 alphanumeric characters from any Azure subscription name. These two segments become the subscription's "identity," carried through every resource name it produces.
Step-by-Step Walkthrough
Given the subscription: "Contoso Infra ITIO Computing Dev"
These two segments, ContosoIn and putingDev, are then adapted for each resource type.
flowchart TD
SUB["Azure Subscription Name\n'Contoso Infra ITIO Computing Dev'"]
CLEAN["Clean: Remove non-alphanumeric\n'ContosoInfraITIOComputingDev'"]
F9["Front9\n'ContosoIn'"]
B9["Back9\n'putingDev'"]
RG["Resource Group\nrg-ContosoInfraITIOComputingDev\n(sub-scoped, full name)"]
LAW["Log Analytics\nlaw-ContosoInfraITIOComputingDev\n(sub-scoped, full name)"]
KV["Key Vault\nkv1ContosoIn-putingDev\n(22/24 chars, F9/B9)"]
SA["Storage Account\nsa11contosoinputingdev\n(22/24 chars, F9/B9 lowercase)"]
VM["Virtual Machine\ndevaz1rgtapp01\n(14/15 chars, region-locked)"]
NIC["NIC\nnic-devaz1rgtapp01"]
DISK["OS Disk\ndisk-devaz1rgtapp01-os"]
SUB --> CLEAN
CLEAN --> RG
CLEAN --> LAW
CLEAN --> F9
CLEAN --> B9
F9 --> KV
B9 --> KV
F9 --> SA
B9 --> SA
VM --> NIC
VM --> DISK
style SUB fill:#f1eeea,stroke:#e0dbd5,color:#162032
style CLEAN fill:#f8f6f3,stroke:#e0dbd5,color:#162032
style F9 fill:#0d7377,stroke:#0a5e61,color:#fff
style B9 fill:#c27a3c,stroke:#a06530,color:#fff
style RG fill:#f8f6f3,stroke:#0d7377,color:#162032
style LAW fill:#f8f6f3,stroke:#0d7377,color:#162032
style KV fill:#f8f6f3,stroke:#0d7377,color:#162032
style SA fill:#f8f6f3,stroke:#0d7377,color:#162032
style VM fill:#f8f6f3,stroke:#e0dbd5,color:#162032
style NIC fill:#f1eeea,stroke:#e0dbd5,color:#7a8694
style DISK fill:#f1eeea,stroke:#e0dbd5,color:#7a8694
Constraint Adaptation
The algorithm doesn't force every resource into the same pattern. It adapts the pattern to each resource type's constraints:
| Resource | Scope | Pattern | Generated Name | Chars | Valid |
|---|---|---|---|---|---|
| Resource Group | Subscription | rg-{fullcleanedsubname} |
rg-ContosoInfraITIOComputingDev |
31/90 | ✓ |
| Key Vault | Global (DNS) | kv{code}{F9}-{B9} |
kv1ContosoIn-putingDev |
22/24 | ✓ |
| Storage Account | Global (DNS) | sa{code}{f9}{b9} |
sa11contosoinputingdev |
22/24 | ✓ |
| Log Analytics | Subscription | law-{fullcleanedsubname} |
law-ContosoInfraITIOComputingDev |
32/63 | ✓ |
| VM | Region-locked | {env}{zone}{type}{purpose}{nn} |
devaz1rgtapp01 |
14/15 | ✓ |
| NIC | Region-locked | nic-{vmname} |
nic-devaz1rgtapp01 |
18/80 | ✓ |
| OS Disk | Region-locked | disk-{vmname}-os |
disk-devaz1rgtapp01-os |
22/80 | ✓ |
The scoping model: Each naming pattern is driven by the resource's Azure scope. Subscription-scoped resources (RG, LAW, VNet) use the full cleaned subscription name because their generous character limits allow it. Globally-unique resources (KV, SA) use F9/B9 extraction because their 24-character limit forces truncation. Region-locked resources (VM, NIC, Disk) encode operational context (environment, region, purpose) because the 15-character limit prevents carrying subscription identity at all.
Design decision: Region codes appear only in region-locked resources (VM, NIC, Disk, NSG). Resource Groups and Log Analytics are subscription-scoped and can span regions, so they carry full subscription identity instead. This prevents a common mistake: putting region in a resource name that isn't physically bound to that region.
The Dash Hierarchy
Dashes aren't random. They encode relationships:
- No dashes (storage account): standalone service, global uniqueness
- Internal dash (kv1ContosoIn-putingDev): separates subscription identity segments
- Prefix dash (nic-vmname): "belongs to" relationship
- Multiple dashes (disk-vmname-os): hierarchical ownership chain
The LL## Safety Prefix
Every Key Vault and Storage Account name begins with a two-letter prefix (kv, sa) followed by a numeric purpose code. This isn't cosmetic; it's a safety guard. Azure requires that Key Vault and Storage Account names start with a letter. But subscription names don't have that constraint. A company called "3M Corporation" has a subscription that starts with a digit.
Without the prefix, Front9 would extract 3MCorpor and produce names like 13MCorpor-.... Some Azure resource types would reject that. The two-letter prefix guarantees the generated name always begins with a letter, regardless of the subscription input.
| Subscription | Without Prefix | With LL## Prefix | Valid? |
|---|---|---|---|
| 3M Corporation Dev | 13MCorpora-rationDev |
kv13MCorpora-rationDev |
✓ (with prefix) |
| 99designs Staging | 1199designsnsstaging |
sa1199designsnsstaging |
✓ (with prefix) |
| Contoso Infra Dev | 1ContosoIn-oInfraDev |
kv1ContosoIn-oInfraDev |
✓ (always safe) |
The pattern is LL##: Two letters (the resource type abbreviation) followed by one or more digits (the purpose code). This creates a fixed-width, type-identifiable prefix that doubles as both a safety guard and a human-readable resource type indicator.
How the Bicep Deployment Wizard Uses It
The Azure Bicep Deployment Wizard is an 8-page React application backed by a Flask API that consumes the Front9/Back9 algorithm to auto-generate every resource name in a deployment package. Engineers enter a subscription name once, and the wizard handles the rest.
flowchart TD
subgraph WIZARD["Bicep Deployment Wizard"]
direction LR
P2["Page 2: Discovery\n(Subscription Name)"]
GEN["AzureNamingGenerator\n(Front9/Back9 Engine)"]
P3["Pages 3-7:\nVM, KeyVault, Storage,\nLogs, Tags"]
P8["Page 8: Preview\n(Validate All Names)"]
PKG["Generate Package"]
P2 -->|"Subscription Name"| GEN
GEN -->|"Auto-fill names\n+ live validation"| P3
P3 --> P8
P8 --> PKG
end
subgraph OUTPUT["Generated Deployment Package"]
direction LR
BKV["keyvault.bicep"]
BVM["vm.bicep"]
BSA["storage-account.bicep"]
DEP["deploy.ps1"]
end
PKG --> OUTPUT
style WIZARD fill:#f8f6f3,stroke:#e0dbd5,color:#162032
style P2 fill:#0d7377,stroke:#0a5e61,color:#fff
style GEN fill:#162032,stroke:#2a3f5f,color:#e8edf3
style P3 fill:#f1eeea,stroke:#e0dbd5,color:#162032
style P8 fill:#f1eeea,stroke:#e0dbd5,color:#162032
style PKG fill:#0d7377,stroke:#0a5e61,color:#fff
style OUTPUT fill:#f8f6f3,stroke:#e0dbd5,color:#162032
style BKV fill:#e6f7ef,stroke:#0d7a50,color:#0d7a50
style BVM fill:#e6f7ef,stroke:#0d7a50,color:#0d7a50
style BSA fill:#e6f7ef,stroke:#0d7a50,color:#0d7a50
style DEP fill:#e6f7ef,stroke:#0d7a50,color:#0d7a50
The wizard validates every generated name against Azure's actual constraints in real-time. If a subscription name produces a Key Vault name that exceeds 24 characters, the engineer sees a validation error before generating any Bicep code. Not after a failed deployment.
The Purpose Code Coordinate System
Key Vault uses a single-digit purpose code (1-9) because Key Vaults are subscription-scoped and don't need region differentiation. Storage Accounts use a two-digit code that encodes two dimensions in a coordinate system:
- First digit (row) — Instance: 1 = Primary, 2 = DR/GFS, 3 = Archive
- Second digit (column) — Purpose: 1 = Boot Diagnostics, 2 = App Data, 3 = Logs/Backup
| 1 — Boot Diag | 2 — App Data | 3 — Logs/Backup | |
|---|---|---|---|
| 1 — Primary | sa11 |
sa12 |
sa13 |
| 2 — DR/GFS | sa21 |
sa22 |
sa23 |
| 3 — Archive | sa31 |
sa32 |
sa33 |
Reading a Storage Account code is like reading a coordinate: sa21 means "DR instance, boot diagnostics." sa13 means "primary instance, logs/backup." You can decode the purpose of any Storage Account from its name alone, without consulting a spreadsheet.
Why Key Vault stays single-digit: Key Vaults are subscription-scoped resources deployed once per subscription, not per region. There's no primary vs. DR distinction, so one dimension (purpose) is sufficient: kv1 = infrastructure secrets, kv2 = application secrets, kv3 = encryption keys.
The full convention supports 9 Key Vault codes and a 10×10 Storage Account coordinate grid. See the Complete Naming Convention Reference for every code, real-world deployment examples, PowerShell helpers, and Terraform patterns.
Why Math Beats Spreadsheets
| Lookup Table Approach | Front9/Back9 (Mathematical) | |
|---|---|---|
| Scalability | Breaks at new subscriptions | Works with ANY subscription name |
| Maintenance | Table must be updated manually | Zero configuration |
| Determinism | Depends on who fills the table | Same input = same output, always |
| Automation | Requires human lookup step | Fully automatable (no human needed) |
| Collision Risk | Abbreviation conflicts at scale | Subscription uniqueness guarantees name uniqueness |
| MSP/Multi-tenant | Separate table per customer | Algorithm handles all customers identically |
The key insight: Subscription names are already globally unique in Azure. Front9/Back9 leverages that existing uniqueness instead of trying to create a new one. The algorithm doesn't invent identity. It extracts it.
Multi-Region: A Full Deployment View
Here's what a complete enterprise deployment looks like using Front9/Back9. The subscription is "Contoso Infra ITIO Computing Dev", deployed across two Azure regions for disaster recovery.
Subscription-Scoped Resources
These resources are deployed once per subscription, not per region. Resource Groups and Log Analytics Workspaces use the full cleaned subscription name because their generous character limits (90 and 63 respectively) don't require F9/B9 extraction.
| Resource | Generated Name | Purpose |
|---|---|---|
| Resource Group | rg-ContosoInfraITIOComputingDev | All application resources (spans regions) |
| Key Vault | kv1ContosoIn-putingDev | Infrastructure secrets (VM passwords, SSH keys) |
| Key Vault | kv2ContosoIn-putingDev | Application secrets (API keys, connection strings) |
| Key Vault | kv3ContosoIn-putingDev | Data encryption keys (TDE, disk encryption) |
| Log Analytics | law-ContosoInfraITIOComputingDev | Centralized monitoring (spans regions) |
West US 2 (Primary Region)
| Resource | Generated Name | Code | Meaning |
|---|---|---|---|
| Storage Account | sa11contosoinputingdev | sa11 | Primary, boot diagnostics |
| Storage Account | sa12contosoinputingdev | sa12 | Primary, app data |
| Storage Account | sa13contosoinputingdev | sa13 | Primary, logs/backup |
| Log Analytics | See subscription-scoped table above | — | |
| VM | devaz1rgtapp01 | — | Dev, AZ1, general, app, instance 01 |
| NIC | nic-devaz1rgtapp01 | — | Belongs to VM |
| OS Disk | disk-devaz1rgtapp01-os | — | VM's OS disk |
East US 2 (DR Region)
| Resource | Generated Name | Code | Meaning |
|---|---|---|---|
| Storage Account | sa21contosoinputingdev | sa21 | DR, boot diagnostics |
| Storage Account | sa22contosoinputingdev | sa22 | DR, app data |
| Storage Account | sa23contosoinputingdev | sa23 | DR, logs/backup |
| Log Analytics | See subscription-scoped table above | — | |
| VM | devaz2rgtapp01 | — | Dev, AZ2, general, app, instance 01 |
| NIC | nic-devaz2rgtapp01 | — | Belongs to VM |
| OS Disk | disk-devaz2rgtapp01-os | — | VM's OS disk |
Notice the coordinate system at work: Every sa1x resource is in the primary region. Every sa2x resource is in DR. You can identify the region and purpose of any Storage Account by reading two digits, without checking the Azure Portal.
The A-Z Sort Property
An underappreciated benefit: when resources are sorted alphabetically in the Azure Portal (the default view), associated resources automatically cluster together. This isn't accidental. It's a direct consequence of how the naming prefixes are structured.
Here's every resource from the deployment above, sorted A-Z exactly as Azure Portal would display them:
| # | Resource Name | Cluster |
|---|---|---|
| 1 | devaz1rgtapp01 | VM cluster (primary) |
| 2 | devaz2rgtapp01 | |
| 3 | disk-devaz1rgtapp01-os | |
| 4 | disk-devaz2rgtapp01-os | VM disks |
| 5 | kv1ContosoIn-putingDev | Key Vaults |
| 6 | kv2ContosoIn-putingDev | |
| 7 | kv3ContosoIn-putingDev | |
| 8 | law-ContosoInfraITIOComputingDev | Log Analytics (sub-scoped) |
| 9 | nic-devaz1rgtapp01 | NICs |
| 10 | nic-devaz2rgtapp01 | |
| 11 | rg-ContosoInfraITIOComputingDev | Resource Group (sub-scoped) |
| 12 | sa11contosoinputingdev | Storage (primary) |
| 13 | sa12contosoinputingdev | |
| 14 | sa13contosoinputingdev | |
| 15 | sa21contosoinputingdev | Storage (DR) |
| 16 | sa22contosoinputingdev | |
| 17 | sa23contosoinputingdev |
The naming convention creates a free indexing system. Disks sort together. Key Vaults sort together. Storage Accounts sort together, and within that group, primary (sa1x) sorts before DR (sa2x). No tags, no filters, no search queries needed. The alphabet does the work.
Tech Stack
Try the Front9/Back9 Demo
Enter any Azure subscription name and see the algorithm generate compliant resource names in real-time, with validation status for every resource type.
Your data stays in your browser. Nothing is saved, collected, or sent to any server. Want proof? Press F12 to open Developer Tools, click the Network tab, and watch. Zero outbound requests. You can also press Ctrl+U to view the full source code, or copy it and paste it into any LLM to verify.
The Bicep Deployment Wizard
The Front9/Back9 algorithm powers a larger tool: the Azure Bicep Deployment Wizard. It's an 8-page React application that consumes the naming engine to auto-generate entire deployment packages. Engineers enter a subscription name once, and the wizard generates validated Bicep templates (Key Vault, VM, Storage, Log Analytics) with correctly named resources, a deploy.ps1 script, and a what-if preview. All before a single Azure API call.
The Bicep Builder uses a fraction of what Front9/Back9 can do. The algorithm itself is fully scalable across any number of subscriptions, resource types, and environments. The wizard is just one application of it.
Your data stays in your browser. The Bicep Wizard runs entirely client-side. No backend calls, no data collection. Press F12 → Network tab to confirm. You can also press F11 to go full-screen and Ctrl+U to view the source.