Azure Functions The pricing tier ‘Dynamic’ is not allowed in this resource group

01/11/2016

If you have been playing around with deploying Azure functions with ARM templates chances are that you have run into the error “The pricing tier ‘Dynamic’ is not allowed in this resource group”. Below you can seethe full error text from a powershell deployment of an Azure Function ARM template


New-AzureRmResourceGroupDeployment : 20:22:44 - Resource Microsoft.Web/serverfarms 'dynamichostingg2wbnrxczqqj2' failed
with message '{
"Code": "Conflict",
"Message": "The pricing tier 'Dynamic' is not allowed in this resource group. Use this link to learn more: http://go.microsoft.com/fwlink/?LinkId=825764",
"Target": null,
"Details": [
{
"Message": "The pricing tier 'Dynamic' is not allowed in this resource group. Use this link to learn more: http://go.microsoft.com/fwlink/?LinkId=825764"
},
{
"Code": "Conflict"
},
{
"ErrorEntity": {
"Code": "Conflict",
"Message": "The pricing tier 'Dynamic' is not allowed in this resource group. Use this link to learn more: http://go.microsoft.com/fwlink/?LinkId=825764",
"ExtendedCode": "04114",
"MessageTemplate": "The pricing tier '{0}' is not allowed in this resource group. Use this link to learn more: http://go.microsoft.com/fwlink/?LinkId=825764",
"Parameters": [
"Dynamic"
],
"InnerErrors": null
}
}
],
"Innererror": null
}'

Unfortunately you can also be the victim of this error if you try to deploy a Azure Function into an existing resource group.

The link in the error text is not that helpful, it just tells you that you cannot deploy Azure functions to an resource group in a scale unit that doesn’t support the dynamic app service plan. And that the limitation will be removed eventually (maybe eventually means never, only Microsoft knows).

Scale units are the underlying hardware and software that Microsoft manages, that Azure web apps runs on top off (azure function is basically an Azure web app with a specific site extension installed, and probably some other changes).

The reason why I got the error in my ARM template was because, I had a classic app service plan (for a web app) in my template together with a dynamic app service plan (for my azure function app). Upon deploying the template Azure Resource Manager picks a scale unit in the location I selected for my app service plans. Since I didn’t put any dependency (by using the dependsOn property in the ARM template), between the dynamic service plan and the classic hosting, I would sometimes get the error because the Azure Resource Manager deployed the classic app service plan first, into a scale unit that didn’t support a dynamic service plan. At other times my template would deploy successfully because the dynamic service plan was deployed first, forcing the Azure Resource Manager to pick a newer (more up-to-date) scale unit.

I already hinted towards the solution to the error. The solution is to deploy the dynamic service plan first. That is simple if you are deploying from scratch with an ARM template, just make the classic service plan dependent on the dynamic service plan. The template I used looks like this.
[js]
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Standard_ZRS",
"Premium_LRS"
],
"metadata": {
"description": "Storage Account type"
}
},
"appServicePlanSku": {
"type": "string",
"allowedValues": [
"Free",
"Shared",
"Basic",
"Standard",
"Premium"
],
"defaultValue": "Basic",
"metadata": {
"description": "The pricing tier of the App Service plan."
}
},
"appServicePlanSize": {
"type": "string",
"defaultValue": "B1",
"allowedValues": [
"F1",
"D1",
"B1",
"B2",
"B3",
"S1",
"S2",
"S3",
"P1",
"P2",
"P3",
"P4"
],
"metadata": {
"description": "The instance size of the App Service Plan."
}
}
},
"variables": {
"storageAccountName": "[concat(‘storage’,uniquestring(resourceGroup().id))]",
"dynamicAppServicePlanName": "[concat(‘dynamichosting’, uniquestring(resourceGroup().id))]",
"appServicePlanName": "[concat(‘appservice’,uniquestring(resourceGroup().id))]",
"functionAppName": "[concat(‘function’,uniquestring(resourceGroup().id))]",
"webAppName": "[concat(‘rncr-‘,uniquestring(resourceGroup().id))]",
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"name": "[variables(‘storageAccountName’)]",
"apiVersion": "2015-06-15",
"location": "[resourceGroup().location]",
"properties": {
"accountType": "[parameters(‘storageAccountType’)]"
}
},
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2015-04-01",
"name": "[variables(‘dynamicAppServicePlanName’)]",
"location": "[resourceGroup().location]",
"properties": {
"name": "[variables(‘dynamicAppServicePlanName’)]",
"computeMode": "Dynamic",
"sku": "Dynamic"
}
},
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
"name": "[variables(‘functionAppName’)]",
"location": "[resourceGroup().location]",
"kind": "functionapp",
"properties": {
"name": "[variables(‘functionAppName’)]",
"serverFarmId": "[resourceId(‘Microsoft.Web/serverfarms’, variables(‘dynamicAppServicePlanName’))]"
},
"dependsOn": [
"[resourceId(‘Microsoft.Web/serverfarms’, variables(‘dynamicAppServicePlanName’))]",
"[resourceId(‘Microsoft.Storage/storageAccounts’, variables(‘storageAccountName’))]"
],
"resources": [
{
"apiVersion": "2016-03-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[resourceId(‘Microsoft.Web/sites’, variables(‘functionAppName’))]",
"[resourceId(‘Microsoft.Storage/storageAccounts’, variables(‘storageAccountName’))]"
],
"properties": {
"AzureWebJobsStorage": "[concat(‘DefaultEndpointsProtocol=https;AccountName=’,variables(‘storageAccountName’),’;AccountKey=’,listkeys(resourceId(‘Microsoft.Storage/storageAccounts’, variables(‘storageAccountName’)), ‘2015-05-01-preview’).key1,’;’)]",
"AzureWebJobsDashboard": "[concat(‘DefaultEndpointsProtocol=https;AccountName=’,variables(‘storageAccountName’),’;AccountKey=’,listkeys(resourceId(‘Microsoft.Storage/storageAccounts’, variables(‘storageAccountName’)), ‘2015-05-01-preview’).key1,’;’)]",
"FUNCTIONS_EXTENSION_VERSION": "latest"
}
}
]
},
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2015-08-01",
"name": "[variables(‘appServicePlanName’)]",
"location": "[resourceGroup().location]",
"dependsOn": [ "[resourceId(‘Microsoft.Web/serverfarms’, variables(‘dynamicAppServicePlanName’))]" ],
"sku": {
"name": "[parameters(‘appServicePlanSize’)]",
"tier": "[parameters(‘appServicePlanSku’)]",
"capacity": 1
}
},
{
"type": "Microsoft.Web/sites",
"apiVersion": "2015-08-01",
"name": "[variables(‘webAppName’)]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat(‘Microsoft.Web/serverFarms/’, variables(‘appServicePlanName’))]"
],
"properties": {
"name": "[variables(‘webAppName’)]",
"serverFarmId": "[variables(‘appServicePlanName’)]",
"siteConfig": {
"AlwaysOn": true
}
},
"resources": [
{
"apiVersion": "2015-08-01",
"type": "config",
"name": "connectionstrings",
"dependsOn": [
"[concat(‘Microsoft.Web/Sites/’, variables(‘webAppName’))]",
"[concat(‘Microsoft.Storage/storageAccounts/’, variables(‘storageAccountName’))]"
],
"properties": {
"AzureWebJobsStorage": {
"value": "[concat(‘DefaultEndpointsProtocol=https;AccountName=’,variables(‘storageAccountName’),’;AccountKey=’,listKeys(resourceId(‘Microsoft.Storage/storageAccounts’, variables(‘storageAccountName’)), ‘2015-06-15′).key1,’;’)]",
"type": "Custom"
},
"AzureWebJobsDashboard": {
"value": "[concat(‘DefaultEndpointsProtocol=https;AccountName=’,variables(‘storageAccountName’),’;AccountKey=’,listKeys(resourceId(‘Microsoft.Storage/storageAccounts’, variables(‘storageAccountName’)), ‘2015-06-15′).key1,’;’)]",
"type": "Custom"
}
}
},
{
"apiVersion": "2015-08-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[resourceId(‘Microsoft.Web/Sites’, variables(‘webAppName’))]"
],
"properties": {
}
}
]
}
],
"outputs": {
}
}
[/js]

But what if you are deploying into an existing resource group? Yes then you are pretty much screwed. The only possible solutions at the moment are:

  1. Wait for the dynamic service plans to eventually be available on all scale units
  2. Take control and move the old resource to a new resource group and hence scale unit, that you ensure supports dynamic service plans. It might not be possible to move all resource as not all resource support moving, see this article for more info

I raised a issue on the github repo used by the Azure function team, to see if they could give some insight into when the limitations would be lifted, unfortunately they didn’t, but they did confirmed that the solution described here is a viable/supported one.

Finally thanks to Tobias Zimmergren, for helping me test the solution and before that keep nagging me for a better solution than just trying to deploy the template again, if it wasn’t for his perseverance I would probably just went back to non-dynamic service plans myself 🙂