1. **Create the slot.** `az webapp deployment slot create -g [rg] -n [app] --slot staging`. Slots need Standard plan or better.
2. **Mark slot-sticky settings.** Connection strings, Key Vault references, and feature flags that differ between staging and prod must be marked "deployment slot setting". Unmarked settings SWAP with the code, so prod suddenly points at the staging database. This is the classic slot incident.
3. **Warmup.** `WEBSITE_SWAP_WARMUP_PING_PATH` and `WEBSITE_SWAP_WARMUP_PING_STATUSES` - the swap waits until the staging slot answers the warmup path with a good status. Without warmup config, the swap can route traffic to a cold/failing instance.
4. **Deploy to staging**, smoke-test against the staging URL (it has the staging settings, sticky ones intact).
5. **Swap.** `az webapp deployment slot swap -g [rg] -n [app] --slot staging --target-slot production`. Or auto-swap for low-risk services (auto-swap swaps on every successful staging deploy; keep it off for anything with migrations).
6. **Migrations.** Run DB migrations separately, backward-compatible (expand then contract), never as part of the swap. The swap is instant; a migration is not.
Traps:
- Forgetting slot-sticky on the database connection string (prod outage with staging data, the worst kind).
- Swap with preview left open blocking the next swap.
- Testing the staging URL but not the warmup path the swap actually pings.
Verify: after swap, prod serves the new version, staging serves the old (it swapped too), and sticky settings are unchanged on both.