Chapter 23 · Azure Reliability
Subchapter 23.9
references/services/app-service/reliability.mdMarkdown10 KBView on GitHub
| Plan | Zone Redundancy | Min Instances | Health Check |
|---|---|---|---|
| Free/Shared (F1/D1) | ❌ Not supported | N/A | ❌ |
| Basic (B1/B2/B3) | ❌ Not supported | N/A | ✅ |
| Standard (S1/S2/S3) | ❌ Not supported | N/A | ✅ |
| Premium v2 (P1v2+) | ✅ zoneRedundant: true + capacity: 2 | 2 | ✅ |
| Premium v3 (P0v3+) | ✅ zoneRedundant: true + capacity: 2 | 2 (recommended) | ✅ |
| Premium v4 (P0v4+) | ✅ zoneRedundant: true + capacity: 2 | 2 (recommended) | ✅ |
| Isolated v2 (I1v2+) | ✅ zoneRedundant: true + capacity: 2 | 2 | ✅ |
⚠️ Output format: Use
--query "data[]" -o jsonforaz graph query.-o tableonly shows summary columns (Count,Total_records) and hides projected fields. Standardaz webappcommands work fine with-o table.
az graph query -q "
resources
| where resourceGroup =~ '<rg>'
| where type =~ 'microsoft.web/serverfarms'
| where kind !contains 'functionapp'
| project name, sku=sku.name, capacity=sku.capacity, zoneRedundant=properties.zoneRedundant, location
" --subscriptions <sub-id> --query "data[]" -o jsonaz webapp config show --name <app> --resource-group <rg> \
--query "{healthCheckPath:healthCheckPath, alwaysOn:alwaysOn}" -o tableaz webapp show --name <app> --resource-group <rg> \
--query "clientAffinityEnabled" -o tsvWhen true, sticky sessions pin clients to a single instance and defeat zone load balancing.
az webapp deployment slot list --name <app> --resource-group <rg> \
--query "[].{name:name, state:state}" -o tableAuto Heal automatically restarts or mitigates your web app when it hits defined thresholds. Can be configured via Azure Portal, CLI or ARM/Bicep
Azure Portal - App Service -> Diagnose and solve problems -> Auto-heal (under Diagnostic Tools) or directly: App Service -> Configuration -> General settings -> Auto Heal
CLI
az webapp config set --resource-group <rg> --name <app> --auto-heal-enabled true
# Rules must be set via ARM PATCH (CLI doesn't expose autoHealRules directly)
az rest --method patch \
--uri "https://management.azure.com/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{app}/config/web?api-version=2022-03-01" \
--body '{"properties":{"autoHealEnabled":true,"autoHealRules":{...}}}'# Check current SKU
az appservice plan show --name <plan> --resource-group <rg> --query "sku"
# Upgrade to Premium v3 (if currently on lower tier)
az appservice plan update \
--name <plan> \
--resource-group <rg> \
--sku P1v3# Set min instances (required for ZR)
az appservice plan update \
--name <plan> \
--resource-group <rg> \
--number-of-workers 2
# Enable ZR
az resource update \
--resource-group <rg> \
--name <plan> \
--resource-type "Microsoft.Web/serverfarms" \
--set properties.zoneRedundant=true⚠️ Enabling zone redundancy may require scaling up first — for the supported App Service plans listed above, set the plan to at least 2 instances before enabling ZR.
# Enable health check
az webapp config set \
--name <app> \
--resource-group <rg> \
--generic-configurations '{"healthCheckPath": "/api/health"}'⚠️ Warning: Enabling health check causes an app restart. Configure during maintenance window.
WEBSITE_HEALTHCHECK_MAXPINGFAILURES)az webapp config set \
--name <app> \
--resource-group <rg> \
--always-on trueApp Service enables ARR affinity by default, which pins each client to a single instance via the ARRAffinity cookie. This defeats zone-load-balancing and any multi-region routing, so it should be disabled for stateless apps:
az webapp update --name <app> --resource-group <rg> \
--client-affinity-enabled falseLeave it on only if your app stores state in instance memory and you cannot move it to a shared cache / database.
Deployment slots complement reliability by enabling safe deployments:
# Create staging slot
az webapp deployment slot create \
--name <app> \
--resource-group <rg> \
--slot staging
# Deploy to staging first, then swap
az webapp deployment slot swap \
--name <app> \
--resource-group <rg> \
--slot staging \
--target-slot production| Plan | Automatic Backup | Custom Backup |
|---|---|---|
| Free/Shared (F1/D1) | ❌ Not supported | ❌ Not supported |
| Basic (B1/B2/B3) | ✅ | ✅ Configuration required |
| Standard (S1/S2/S3) | ✅ | ✅ Configuration required |
| Premium v2 (P1v2+) | ✅ | ✅ Configuration required |
| Premium v3 (P0v3+) | ✅ | ✅ Configuration required |
| Premium v4 (P0v4+) | ✅ | ✅ Configuration required |
| Isolated v2 (I1v2+) | ✅ | ✅ Configuration required |
AVM modules: If the project uses
br/public:avm/res/web/serverfarmorbr/public:avm/res/web/site, the parameter names differ from raw ARM (e.g.zoneRedundantandskuCapacityare top-level params;siteConfigis usually preserved). Always grep the actual module call (Select-String -Path infra -Recurse -Pattern "avm/res/web/" -Context 0,15) and patch the params already in use. The raw-Bicep examples below show the property paths to translate.
resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
name: planName
location: location
sku: {
name: 'P0v3'
capacity: 2 // ← ADD (min 2 for ZR on P1v3)
}
properties: {
reserved: true // Linux
zoneRedundant: true // ← ADD
}
}resource webApp 'Microsoft.Web/sites@2023-12-01' = {
name: appName
location: location
properties: {
serverFarmId: appServicePlan.id
siteConfig: {
healthCheckPath: '/api/health' // ← ADD
alwaysOn: true // ← ADD (recommended)
}
}
}resource "azurerm_service_plan" "plan" {
name = var.plan_name
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
os_type = "Linux"
sku_name = "P1v3"
worker_count = 2 # ← ADD (min 2 for ZR)
zone_balancing_enabled = true # ← ADD
}resource "azurerm_linux_web_app" "app" {
name = var.app_name
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
service_plan_id = azurerm_service_plan.plan.id
site_config {
health_check_path = "/api/health" # ← ADD
always_on = true # ← ADD
}
}When the parent skill builds the feature-pivoted assessment table, report each App Service resource on the relevant rows:
| Feature row | What to report |
|---|---|
| Zone redundancy — compute | 🟢 ON if the plan has zoneRedundant: true AND sku.capacity ≥ 2. 🔴 OFF if either is missing or the plan tier doesn’t support ZR (Free / Shared / Basic / Standard). Annotate (needs plan upgrade) for unsupported tiers. |
| Health probes | 🟢 ON if siteConfig.healthCheckPath is set on the app. 🔴 OFF if empty. Basic tier and above support it; Free/Shared do not — annotate (needs plan upgrade) in that case. |
| Multi-region failover | 🟢 ON if the same app is deployed in ≥2 regions behind Front Door / Traffic Manager. 🟡 PARTIAL if multi-region is set up but clientAffinityEnabled is still true (sticky sessions break failover). 🔴 OFF otherwise. |