App Service Deployment Slots
Zero-downtime deployments using staging slots.
Basic Staging Slot
resource stagingSlot 'Microsoft.Web/sites/slots@2022-09-01' = {
parent: webApp
name: 'staging'
location: location
properties: {
serverFarmId: appServicePlan.id
}
}Slot Requirements — App Service
| SKU Tier | Slots Supported |
|---|---|
| Free/Shared | 0 |
| Basic | 0 |
| Standard | 5 |
| Premium | 20 |
Slot Requirements — Azure Functions
⚠️ Slot support for Azure Functions varies by OS and hosting plan.
| Hosting Plan | OS | Slots Supported |
|---|---|---|
| Flex Consumption (FC1) | Linux | ❌ 0 |
| Consumption (Y1) | Windows | ✅ 1 staging slot |
| Consumption (Y1) | Linux | ❌ 0 |
| Elastic Premium (EP1-EP3) | Windows or Linux | ✅ 20 slots |
| Dedicated (Standard+) | Windows or Linux | ✅ 5–20 slots |
💡 For Azure Functions requiring deployment slots:
- Windows Consumption (Y1) supports 1 staging slot — this is a supported platform capability.
If you need it, use it. See the Bicep example below.
- Recommendation for new projects: prefer Elastic Premium (EP1+) (no cold starts, VNet integration)
or a Dedicated plan (Standard+). Y1 cold starts can affect slot swap warm-up reliability.
- Linux Consumption and Flex Consumption do not support deployment slots.
Windows Consumption Function App with Staging Slot (Bicep)
resource functionAppPlan 'Microsoft.Web/serverfarms@2022-09-01' = {
name: '${resourcePrefix}-funcplan-${uniqueHash}'
location: location
sku: { name: 'Y1', tier: 'Dynamic' }
// No 'reserved: true' — Windows Consumption
}
resource functionApp 'Microsoft.Web/sites@2022-09-01' = {
name: '${resourcePrefix}-${serviceName}-${uniqueHash}'
location: location
kind: 'functionapp' // Windows (no 'linux' suffix)
identity: { type: 'SystemAssigned' }
properties: {
serverFarmId: functionAppPlan.id
httpsOnly: true
siteConfig: {
appSettings: [
{ name: 'WEBSITE_NODE_DEFAULT_VERSION', value: '~20' }
{ name: 'FUNCTIONS_EXTENSION_VERSION', value: '~4' }
{ name: 'FUNCTIONS_WORKER_RUNTIME', value: 'node' }
{ name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING', value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value}' }
{ name: 'WEBSITE_CONTENTSHARE', value: '${toLower(serviceName)}-prod' }
{ name: 'AzureWebJobsStorage', value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value}' }
{ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING', value: applicationInsights.properties.ConnectionString }
]
}
}
}
// Staging slot — only 1 staging slot supported on Consumption
resource stagingSlot 'Microsoft.Web/sites/slots@2022-09-01' = {
parent: functionApp
name: 'staging'
location: location
kind: 'functionapp'
properties: {
serverFarmId: functionAppPlan.id
siteConfig: {
appSettings: [
{ name: 'WEBSITE_NODE_DEFAULT_VERSION', value: '~20' }
{ name: 'FUNCTIONS_EXTENSION_VERSION', value: '~4' }
{ name: 'FUNCTIONS_WORKER_RUNTIME', value: 'node' }
{ name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING', value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value}' }
{ name: 'WEBSITE_CONTENTSHARE', value: '${toLower(serviceName)}-staging' } // MUST differ from production
{ name: 'AzureWebJobsStorage', value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value}' }
{ name: 'APPLICATIONINSIGHTS_CONNECTION_STRING', value: applicationInsights.properties.ConnectionString }
]
}
}
}⚠️
WEBSITE_CONTENTSHAREmust be unique per slot on Windows Consumption — each slot needs its own file share. Use slot-sticky settings (viaslotConfigNames) forWEBSITE_CONTENTSHAREandWEBSITE_CONTENTAZUREFILECONNECTIONSTRINGso these values do not swap with production.
Deployment Flow
- Deploy to staging slot
- Warm up and test staging
- Swap staging with production
- Rollback by swapping again if needed
Slot Settings
Configure settings that should not swap:
resource slotConfigNames 'Microsoft.Web/sites/config@2022-09-01' = {
parent: webApp
name: 'slotConfigNames'
properties: {
appSettingNames: [
'APPLICATIONINSIGHTS_CONNECTION_STRING'
]
}
}