Use uniqueString() function to generate unique names for resources in ARM template

When playing with ARM templates in a team, you need a way to come up with unique names for your DNS dependent resources on Azure like storage accounts and public IPs. There is a function that has been released recently that will help you a lot with this need, the uniqueString() function.

Unique but Non-Deterministic

Having a unique value each time you perform a deployment is not very useful when dealing with ARM template. I should add, you definitely don't want to do that as it goes against the deterministic state you intend to have in an ARM template.

A good example of this is if you use a GUID to be unique. You cannot, let say, use [Guid]::NewGuid() in PowerShell to generate a parameter value for a storage account simply because each time you'll deploy your template, you'll end up creating a new storage account, not really what you want.

Unique but deterministic... Say hello to uniqueString()

uniqueString (stringForCreatingUniqueString, ...)

What does this function?

Performs a 64-bit hash of the provided strings to create a unique string. This function is helpful when you need to create a unique name for a resource. You provide parameter values that represent the level of uniqueness for the result. You can specify whether the name is unique for your subscription, resource group, or deployment.

The returned value is not a completely random string, but rather the result of a hash function. The returned value is 13 characters long. It is not guaranteed to be globally unique. You may want to combine the value with a prefix from your naming convention to create a more friendly name.

You can use uniqueString() with the id of a subscription or resource group depending at which level you need the hashed result. You can even provide more than one parameter, all extra parameters will add to the hash calculation. An example of this is the following:
"[uniqueString( resourceGroup().id, deployment().name )]"

If you use the id of a subscription, the computed hash will change only when you deploy your template to a different subscription. It can be handful if you use different subscriptions as boundaries. Usually people have multiple resources in the same subscription so this option is good but not flexible enough in my scenario with multiple team members.

What I usually suggest when dealing with a team of many developers is that each team member deploy in their own resource group. You can then use a unique prefix for your project or team to obtain global unique name.

[concat( parameters('storageNamePrefix'), uniqueString(resourceGroup().id) )]

Complete example

Here is a complete example that creates a storage account.

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageNamePrefix": {
      "type": "string",
      "metadata": {
        "description": "The prefix string to add to a generated string that is unique to the resourceGroup."
      }
    }
  },
  "variables": {
    "storageName": "[toLower( concat( parameters('storageNamePrefix'), uniqueString(resourceGroup().id) ) )]",
    "location": "[resourceGroup().location]"
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[variables('storageName')]",
      "apiVersion": "2015-06-15",
      "location": "[variables('location')]",
      "properties": {
        "accountType": "Standard_LRS"
      }
    }
  ],
  "outputs": {
    "storageAccountName": {
      "type": "string",
      "value": "[variables('storageName')]"
    }
  }
}

Hope it help you in your unique naming quest!

Resources

I am the proud father of two little gems. A beer & wine enthusiasm. For everything else, I work and play with Azure at day, and I am an Azure MVP & Advisor at night.
Montreal, Canada