Skip to content

App Service Deployment Slots Support - Phase 1 #6526

@puicchan

Description

@puicchan

Summary

Add support for deploying to Azure App Service deployment slots to enable zero-downtime deployments with staging validation before production promotion.

Problem

Currently, azd deploy deploys directly to the production App Service. Teams need to:

  • Deploy to a staging slot for validation
  • Promote staging to production with zero downtime
  • Rollback quickly if issues are detected

This workflow is a standard best practice for production deployments but requires manual intervention outside of azd.

Proposed Solution

New CLI Commands

Deploy to Slot

azd deploy <service> --to <slot-name>
azd deploy <service> --from-package <package-path> --to <slot-name>

Examples:

azd deploy web --to staging                                  # deploy to staging slot
azd deploy web --from-package ./dist/web.zip --to staging  # deploy package to staging

Promote to Production (Traffic Shift)

azd deploy <service> --traffic <slot-name>:100

Examples:

azd deploy web --traffic staging:100      # promote staging to production (triggers swap)
azd deploy web --traffic production:100   # rollback (swap back)

Interactive confirmation before swap:

Ready to shift 100% traffic to staging (this will swap slots):
  Current production:
    Version: azd-deploy-20260107-1015
  Staging (will become production):
    Version: azd-deploy-20260107-1210

Proceed with traffic shift? (Y/n)

Check Deployment Status

azd deploy <service> --status

Shows current version/URL for each slot (production, staging, etc.).

User Workflow

# 1. Deploy to staging
azd deploy web --to staging

# 2. Test staging
# ... run tests against staging URL ...

# 3. Promote to production
azd deploy web --traffic staging:100

# 4. Rollback if needed
azd deploy web --traffic production:100

Prerequisites (User Setup)

Users must manually add slot infrastructure:

Bicep with AVM module:

module stagingSlot 'br/public:avm/res/web/site/slot:0.2.0' = { ... }

output SERVICE_WEB_STAGING_URI string = 'https://${stagingSlot.outputs.name}.azurewebsites.net'
output SERVICE_WEB_STAGING_NAME string = stagingSlot.outputs.name

Requirements:

  • App Service Plan must be Standard S1+ or Premium tier (Basic/Free don't support slots)
  • Slot infrastructure outputs must follow naming convention: SERVICE_{SERVICENAME}_{SLOTNAME}_URI

Optional azure.yaml default:

services:
  web:
    project: .
    language: py
    host: appservice
    deployment:
      slot: staging  # default slot when using --to without argument

Implementation Considerations

1. Infrastructure Detection

  • Read azure.yaml to identify services and optional default slot (deployment.slot)
  • Read azd provision outputs to detect which slots exist in infrastructure (don't parse IaC files)
  • Required outputs: SERVICE_{SERVICENAME}_{SLOTNAME}_URI, SERVICE_{SERVICENAME}_{SLOTNAME}_NAME
  • Works with any IaC tool (Bicep, Terraform)
  • Clear error if outputs missing with guidance on adding slot infrastructure

2. Deployment Type Detection

  • Only support code-based App Service deployments (zip deploy, run from package)
  • Error if user attempts slot operations on Web App for Containers: "Deployment slots for containerized App Services are not yet supported. Use Azure Container Apps for container-based blue/green deployments."

3. Traffic Management (Swap)

  • For App Service: --traffic <slot>:100 triggers atomic slot swap
  • Only 0% or 100% supported (binary traffic model)
  • Interactive confirmation before swap with version info
  • Track deployment version in app settings (AZD_DEPLOYMENT_VERSION) for visibility

4. Version Tracking

Store deployment metadata in slot app settings for auditing:

  • CI/CD: Extract from environment variables (commit hash, branch, build number)
  • Local dev: Generate identifier azd-deploy-YYYYMMDD-HHMM
  • Mark as slot-specific (sticky) so version stays with slot during swap

5. Configuration Management

  • Phase 1: All slots share same configuration from azd environment (.azure/<env-name>/.env)
  • For slot-specific config needs: use multiple azd environments (Pattern 2)
  • Future (Phase 3): Native slot-specific configuration support

6. Error Handling

  • Clear error if slot doesn't exist
  • Clear error if App Service Plan SKU doesn't support slots
  • Graceful handling if swap fails (Azure API errors)
  • Best-effort warning if deployment appears in progress

7. User Experience

  • Show clear progress during traffic shift
  • Display slot URLs after deployment
  • Warnings before destructive operations
  • Show version info before/after traffic shifts
  • Maintain backward compatibility (no flags = deploy to production)

8. Telemetry (Required)

Track usage metrics to inform Phase 2-4 decisions:

  • deploy.to - deployment to slot
  • deploy.traffic - traffic shift operation
  • deploy.status - status check
  • Success/failure rates, operation latency, slot names used

9. Known Limitations

  • No concurrent operation protection (document to avoid simultaneous operations)
  • Shared configuration across slots (until Phase 3)
  • Code-based App Service only (no container support)

Design Principles

  1. Generic interface: Use --to flag that will extend to Container Apps in Phase 2
  2. Leverage existing features: Use existing --from-package for artifact promotion
  3. Output-based detection: Read provision outputs, not IaC files
  4. Backward compatible: No breaking changes; existing behavior unchanged without flags
  5. Infrastructure-agnostic: Works with Bicep, Terraform, ARM

Success Criteria

  1. Users can deploy to staging slot with single command
  2. Traffic shift operation completes in < 10 seconds
  3. Zero downtime during traffic shift
  4. Clear error messages guide users to correct configuration
  5. 90% of users successfully deploy with slots on first attempt

Out of Scope (Future Phases)

  • Phase 2: Container Apps revision support with same --to interface
  • Phase 3: Auto-provision slots, slot-specific configuration, concurrency protection
  • Phase 4: TBD

References

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions