Deployment Slots Validation¶
Use staging slots to validate deployments before production swap, with health checks and automated safeguards in GitHub Actions.
flowchart TD
A[Create staging slot] --> B[Set slot-sticky config]
B --> C[Deploy release.zip to staging]
C --> D[Run /health /info /readyz checks]
D --> E{All checks pass?}
E -- Yes --> F[Swap to production]
E -- No --> G[Stop and fix staging] Prerequisites¶
- App Service plan supports deployment slots (Standard, Premium, or Isolated)
- Production app already running on Linux App Service
- GitHub Actions workflow configured for the repository
Main content¶
1) Create staging slot¶
Create a new deployment slot named staging for your application:
az webapp deployment slot create \
--resource-group "$RG" \
--name "$APP_NAME" \
--slot "staging" \
--output json
| Flag | Description |
|---|---|
--resource-group "$RG" | Creates the slot under the resource group that contains the production app. |
--name "$APP_NAME" | Selects the web app that will receive the new deployment slot. |
--slot "staging" | Names the new slot staging. |
--output json | Returns the created slot configuration as JSON. |
2) Configure slot-sticky settings¶
Mark environment-specific values as slot settings so they do not swap with the code:
az webapp config appsettings set \
--resource-group "$RG" \
--name "$APP_NAME" \
--slot "staging" \
--slot-settings APP_ENV=staging FEATURE_BETA_ENABLED=true \
--output json
| Flag | Description |
|---|---|
--resource-group "$RG" | Targets the resource group that contains the slot. |
--name "$APP_NAME" | Selects the web app whose staging slot settings will be updated. |
--slot "staging" | Applies the configuration change to the staging slot instead of production. |
--slot-settings APP_ENV=staging FEATURE_BETA_ENABLED=true | Writes slot-sticky app settings that stay with the staging slot during swaps. |
--output json | Returns the updated settings payload as JSON. |
3) Deploy artifact to staging slot¶
Deploy your Python application package directly to the staging slot:
az webapp deploy \
--resource-group "$RG" \
--name "$APP_NAME" \
--slot "staging" \
--src-path "release.zip" \
--type zip \
--output json
| Flag | Description |
|---|---|
--resource-group "$RG" | Targets the resource group that contains the staging slot. |
--name "$APP_NAME" | Selects the web app that should receive the deployment. |
--slot "staging" | Deploys the package to the staging slot instead of production. |
--src-path "release.zip" | Uploads the release.zip package as the deployment artifact. |
--type zip | Tells App Service to treat the uploaded artifact as a Zip Deploy package. |
--output json | Returns deployment details as JSON. |
4) Add explicit health endpoint checks¶
Verify the staging slot is responding correctly before proceeding with the swap:
curl --fail --silent "https://$APP_NAME-staging.azurewebsites.net/health"
curl --fail --silent "https://$APP_NAME-staging.azurewebsites.net/info"
5) Add version-aware validation endpoint¶
Implement a /readyz route in your Flask application to provide environment and version context:
import os
from flask import Flask, jsonify
app = Flask(__name__)
@app.route("/readyz")
def readyz():
return jsonify({
"status": "ready",
"environment": os.environ.get("APP_ENV", "production"),
"buildVersion": os.environ.get("BUILD_VERSION", "unknown"),
})
6) Swap staging to production¶
Perform the swap to promote the validated staging code to the production slot:
az webapp deployment slot swap \
--resource-group "$RG" \
--name "$APP_NAME" \
--slot "staging" \
--target-slot "production" \
--output json
| Flag | Description |
|---|---|
--resource-group "$RG" | Targets the resource group that contains the source and target slots. |
--name "$APP_NAME" | Selects the web app whose slots will be swapped. |
--slot "staging" | Uses the staging slot as the source of the swap. |
--target-slot "production" | Promotes the staging slot into the production slot. |
--output json | Returns swap-operation details as JSON. |
7) Optional auto-swap configuration¶
Enable auto-swap to automatically promote successful deployments to production:
az webapp deployment slot auto-swap \
--resource-group "$RG" \
--name "$APP_NAME" \
--slot "staging" \
--auto-swap-slot "production" \
--output json
| Flag | Description |
|---|---|
--resource-group "$RG" | Targets the resource group that contains the slot configuration. |
--name "$APP_NAME" | Selects the web app whose slot should auto-swap. |
--slot "staging" | Enables auto-swap on the staging slot. |
--auto-swap-slot "production" | Configures production as the automatic swap target. |
--output json | Returns the updated auto-swap configuration as JSON. |
Linux Limitation
Auto-swap is not supported for web apps on Linux and Web App for Containers. Use manual swap or CI/CD-triggered swap instead. See Deployment Slots for details.
8) GitHub Actions staged deployment example¶
Automate the deployment, validation, and swap process using GitHub Actions:
jobs:
deploy-staging:
runs-on: ubuntu-latest
steps:
- name: Deploy to Staging Slot
uses: azure/webapps-deploy@v3
with:
app-name: ${{ env.APP_NAME }}
slot-name: 'staging'
package: .
validate:
needs: deploy-staging
runs-on: ubuntu-latest
steps:
- name: Health Check
run: |
curl --fail --retry 5 --retry-delay 5 \
"https://${{ env.APP_NAME }}-staging.azurewebsites.net/readyz"
swap:
needs: validate
runs-on: ubuntu-latest
steps:
- name: Swap to Production
run: |
az webapp deployment slot swap \
--resource-group ${{ env.RG }} \
--name ${{ env.APP_NAME }} \
--slot staging \
--target-slot production
| Command | Description |
|---|---|
az webapp deployment slot swap --resource-group ${{ env.RG }} --name ${{ env.APP_NAME }} --slot staging --target-slot production | Swaps the validated staging deployment into production from the GitHub Actions job. |
Validate before swap, always
A successful deployment is not the same as a healthy runtime. Require endpoint validation and telemetry checks before production swap.
Verification¶
- Staging slot serves the expected build version via
/readyz. - Production remains stable and unaffected during staging validation.
- Swap completes without environment configuration leakage.
- Post-swap production
/healthendpoint returns a success status.
Troubleshooting¶
Staging healthy, production fails after swap¶
- Check that slot-sticky configurations (like
APP_ENV) are correctly marked. - Verify that database connection strings or external API keys are valid for production.
- Confirm the production App Service plan has sufficient resources for the new build.
Swap operation blocked¶
Ensure no other management operations are running on the App Service. Check the Azure Activity Log for specific conflict errors or pending restarts.
Auto-swap caused unexpected release¶
Disable auto-swap and revert to manual swap or a controlled GitHub Actions workflow. Ensure that the staging slot is fully warmed up before auto-swap triggers.
Run It in the Portal¶
Portal view: Deployment slots with Swap dialog (validated promotion)¶

Purpose: Show the configuration changes a swap will apply before you start it.
Look for: The Source and Target slots, Perform swap with preview, and the Config Changes table.
Expected result: The table lists every setting that changes on swap; review each row before selecting Start Swap.
The Deployment slots blade with the Swap panel open is the Portal counterpart to the az webapp deployment slot swap command this recipe drives from CI. The Source: app-test-20251107-staging and Target: app-test-20251107 selectors mirror the staging-to-production promotion direction the recipe validates against. The Config Changes table at the bottom previews how slot-sticky settings will move during the swap, including the APPLICATIONINSIGHTS_CONNECTION_STRING and SCM_DO_BUILD_DURING_DEPLOYMENT rows visible here — the same delta you should inspect before clicking Start Swap. Use this Portal view as the manual checkpoint complementing the automated pre-swap validation calls (health probe, smoke test) the recipe issues against the staging slot.
See Also¶
- Tutorial: 06. CI/CD
- Tutorial: 03. Configuration
- For platform details, see Azure App Service Guide