-
Notifications
You must be signed in to change notification settings - Fork 102
Fix: Windows Consumption (Y1) correctly supports deployment slots for Azure Functions #1062
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,7 @@ resource stagingSlot 'Microsoft.Web/sites/slots@2022-09-01' = { | |
| } | ||
| ``` | ||
|
|
||
| ## Slot Requirements | ||
| ## Slot Requirements — App Service | ||
|
|
||
| | SKU Tier | Slots Supported | | ||
| |----------|-----------------| | ||
|
|
@@ -24,6 +24,83 @@ resource stagingSlot 'Microsoft.Web/sites/slots@2022-09-01' = { | |
| | 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 | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Linux Consumption also supports slots (1 Slot) but should not be considered in light of deprecation |
||
| | 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 valid for existing apps or specific Windows requirements, | ||
| > but cold starts on Consumption affect slot swap reliability. | ||
| > - **Elastic Premium** is the recommended plan for Functions with slots: no cold starts, full VNet integration. | ||
| > - **Flex Consumption does not support slots** — use Premium or Dedicated if slots are required for new projects. | ||
|
|
||
| ### Windows Consumption Function App with Staging Slot (Bicep) | ||
|
|
||
| ```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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is optional for slots as discussed at https://learn.microsoft.com/en-us/azure/azure-functions/functions-app-settings#website_contentshare |
||
| { name: 'AzureWebJobsStorage', value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value}' } | ||
| { name: 'APPLICATIONINSIGHTS_CONNECTION_STRING', value: applicationInsights.properties.ConnectionString } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| > ⚠️ `WEBSITE_CONTENTSHARE` **must be unique per slot** on Windows Consumption — each slot needs its own file share. | ||
| > Use slot-sticky settings (via `slotConfigNames`) for `WEBSITE_CONTENTSHARE` and `WEBSITE_CONTENTAZUREFILECONNECTIONSTRING` | ||
| > so these values do not swap with production. | ||
|
|
||
| ## Deployment Flow | ||
|
|
||
| 1. Deploy to staging slot | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -137,6 +137,14 @@ resource storageRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04- | |
|
|
||
| **⚠️ Not recommended for new deployments. Use Flex Consumption instead.** | ||
|
|
||
| > 💡 **OS and Slots Matter for Consumption:** | ||
| > - **Linux Consumption** (`kind: 'functionapp,linux'`, `reserved: true`): Does **not** support deployment slots. | ||
| > - **Windows Consumption** (`kind: 'functionapp'`, no `reserved`): Supports **1 staging slot** (2 total including production). | ||
| > If a user specifically needs Windows Consumption with a slot, that is supported — use the Windows pattern below. | ||
| > For new apps needing slots, prefer **Elastic Premium (EP1)** for better performance and no cold-start issues. | ||
|
|
||
| ### Linux Consumption (no slot support) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Linux Consumption also supports 1 slot but should not be recommended in light of deprecation |
||
|
|
||
| ```bicep | ||
| resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { | ||
| name: '${resourcePrefix}func${uniqueHash}' | ||
|
|
@@ -161,16 +169,86 @@ resource functionApp 'Microsoft.Web/sites@2022-09-01' = { | |
| serverFarmId: functionAppPlan.id | ||
| httpsOnly: true | ||
| siteConfig: { | ||
| linuxFxVersion: 'Node|18' | ||
| linuxFxVersion: 'Node|20' | ||
| appSettings: [ | ||
| { name: 'AzureWebJobsStorage', value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value}' } | ||
| { name: 'FUNCTIONS_EXTENSION_VERSION', value: '~4' } | ||
| { name: 'FUNCTIONS_WORKER_RUNTIME', value: 'node' } | ||
| { name: 'APPLICATIONINSIGHTS_CONNECTION_STRING', value: applicationInsights.properties.ConnectionString } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Windows Consumption (supports 1 staging slot) | ||
|
|
||
| > ⚠️ **Windows Consumption is not recommended for new projects** — consider Flex Consumption or Elastic Premium. | ||
| > Use this pattern only for existing Windows apps or when Windows-specific features are required. | ||
|
|
||
| ```bicep | ||
| resource functionAppPlan 'Microsoft.Web/serverfarms@2022-09-01' = { | ||
| name: '${resourcePrefix}-funcplan-${uniqueHash}' | ||
| location: location | ||
| sku: { name: 'Y1', tier: 'Dynamic' } | ||
| // No 'reserved: true' for Windows | ||
| } | ||
|
|
||
| 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 } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // 1 staging slot is supported on Windows 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 } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Sticky settings — do not swap WEBSITE_CONTENTSHARE between slots | ||
| resource slotConfigNames 'Microsoft.Web/sites/config@2022-09-01' = { | ||
| parent: functionApp | ||
| name: 'slotConfigNames' | ||
| properties: { | ||
| appSettingNames: [ | ||
| 'WEBSITE_CONTENTSHARE' | ||
| 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING' | ||
| ] | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Service Bus Integration (Managed Identity) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Y1 also supports the 1 staging slot. We need to decouple the support of slots with our guidance whether to use Y1 or not. While we don't recommend it, if you *need it, it can be done and it has the slot
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in 651b804. The guidance callout now leads with the factual statement ("Windows Consumption Y1 supports 1 staging slot — this is a supported platform capability. If you need it, use it.") and separates that cleanly from the recommendation ("for new projects, prefer Elastic Premium or Dedicated"). The two concerns are now independent.