A team releases a new version of an API on Azure App Service the way Microsoft recommends: deploy it to a staging slot, test it there, swap it into production. The swap takes a few minutes, no request fails, and the availability chart never dips. Then the reports arrive. An export running on the old instances never finished. A job scheduled every fifteen minutes ran twice during the swap, once in each slot. And when the new version misbehaves and the team swaps back, the old version fails on rows the new one wrote.
Nothing malfunctioned. A swap guarantees where new requests go; it makes no promise about the work already running, the work no request started, or the data the new version wrote. Microsoft documents most of what falls outside the promise, in notes across several pages, and leaves the rest undocumented. Zero downtime and nothing lost are different properties, and a swap offers the first.
This analysis covers deployment slots in Azure App Service, and in Azure Functions on the Consumption, Premium and Dedicated plans, the Functions plans that have them. Microsoft's documentation was checked on 7 November 2026. No tenant or subscription was accessed.
What the swap guarantees
Slots exist in the Standard, Premium and Isolated tiers of an App Service plan, and each is a live app with its own host name (Set up staging environments in Azure App Service). In outline, from the same page, a swap from staging into production runs in this order:
- Production's slot-specific settings are applied to every staging instance, and each instance restarts.
- "If any instance fails to restart, the swap operation reverts all changes to the source slot and stops the operation."
- Each instance is warmed up with HTTP requests.
- "If all instances on the source slot are warmed up successfully, swap the two slots by switching their routing rules."
- The slot now holding the previous version has its own settings applied, and its instances restart.
Throughout, "the target slot remains online while the source slot is being prepared and warmed up, regardless of whether the swap succeeds or fails". Hence the guarantees Microsoft states: warming first "eliminates downtime", "No requests are dropped because of swap operations", and the same swap performed "immediately" brings back the "last known good site". The swap also "warms up the necessary worker instances to match your production scale" (deployment best practices).
Swap with preview "pauses after the first step", so the staging slot can be checked with the settings it will have in production. Auto swap runs the whole sequence after every deployment to the slot, and "isn't supported in web apps on Linux and in Web App for Containers" (staging environments, above).
For Azure Functions, Microsoft is more guarded: "Slot swaps don't guarantee zero downtime. Currently executing functions can be terminated and degraded availability can occur on scaled apps during slot swap operations" (Azure Functions deployment slots). The same page sets the limits: two slots on Consumption and none on Flex Consumption; function keys reset by a swap when stored in files; swaps that can fail with a network-secured default storage account; app names under 32 characters, to avoid host ID collisions.
Warmed up means answered
The warm-up is often read as a test, and by default it is not one. "If an instance returns any HTTP response, it's considered to be warmed up", and of the list of acceptable status codes Microsoft says "By default, all response codes are valid" (staging environments, above). An instance that answers / with a 500 is warm.
Three things change what it checks, all on the same page. WEBSITE_SWAP_WARMUP_PING_PATH sets the path requested, / by default. WEBSITE_SWAP_WARMUP_PING_STATUSES lists the codes that count: "If the returned status code isn't in the list, the warm-up and swap operations are stopped." An applicationInitialization element in Web.config names pages to request, and "The swap operation waits for this custom warm-up to finish". Each request gets 90 seconds and up to five retries; if every retry times out, the swap stops.
Our reading: by default, a swap proves that the new version starts and answers on each instance. That it reaches its database or serves the requests that matter is proved only if the warm-up path exercises them and only success codes are accepted. Illustrative configuration only; the path is one the application must implement:
# Illustrative: the same values in every slot
WEBSITE_SWAP_WARMUP_PING_PATH=/health/ready
WEBSITE_SWAP_WARMUP_PING_STATUSES=200What moves with the code, and what stays
A swap carries some configuration with the code and leaves the rest with the slot. Microsoft's lists, abridged:
| Moves with the code | Stays with the slot |
|---|---|
| App settings and connection strings, unless marked as deployment slot settings | Custom domain names, nonpublic certificates and TLS/SSL settings |
| Mounted storage accounts, unless marked as slot settings | Scale settings and Always On |
| Language framework version, 32-bit or 64-bit, WebSockets | IP restrictions, CORS and diagnostic log settings |
| Handler mappings, path mappings and public certificates | Managed identities and virtual network integration |
| WebJobs content | WebJobs schedulers, and settings ending in _EXTENSION_VERSION |
Source for the table, checked on 7 November 2026: which settings are swapped. Some in the second column, such as IP restrictions and CORS, become swappable with WEBSITE_OVERRIDE_PRESERVE_DEFAULT_STICKY_SLOT_SETTINGS=0 in every slot, never one by one.
Every setting is a decision. A setting not marked as a deployment slot setting goes to production with the code, so a staging connection string left unmarked becomes production's. Functions adds the opposite trap: a staging slot created in the portal starts with "all existing settings from the production slot ... regardless of the stickiness of the setting" (Functions deployment slots, above). Our reading: until they are changed, code deployed to the new slot listens to production's queues. Microsoft advises marking settings "related to event sources and bindings" as slot settings "before you start a swap", and defining each slot setting in every slot.
The identity stays behind. "The managed identity configuration is specific to the slot" (managed identities for App Service and Azure Functions): code tested in staging called its dependencies as the staging identity, and after the swap calls them as production's. A change to an identity's group or role membership can take "up to around 24 hours" to apply, the same page warns. Our reading: grant production's identity what the new version needs the day before the swap.
So does the Functions runtime version. FUNCTIONS_EXTENSION_VERSION ends in _EXTENSION_VERSION, so it stays with its slot. Microsoft's migration guide to version 4.x makes the swap carry it only with WEBSITE_OVERRIDE_STICKY_EXTENSION_VERSIONS=0 set in production, and in its minimum-downtime variant, swapping back first means removing that setting from production, a change that "would then cause a restart".
What the swap abandons
Work in progress
A note on the swap page bounds the promise: "Those instances are recycled in the last step of the swap process. If you have any long-running operations in your application, they're abandoned when the workers recycle. This fact also applies to function apps" (staging environments, above). The Flex Consumption page makes the comparison outright: "Rolling updates preserve in-progress executions, while deployment slots terminate them during swaps" (site update strategies in Flex Consumption). Work a function starts without waiting for is not tracked at all, and shutdown can leave it "in an unknown state" (performance and reliability).
"No requests are dropped" and "abandoned" describe different moments: the routing switch, and the old instances afterwards. Microsoft does not document how long the old instances keep serving requests already under way before they are recycled, or whether a request received just before the switch is guaranteed to complete. Our reading: an export, a long upload or a synchronous call to a slow dependency can be abandoned, and its client sees a lost response. If the client retries a write, it can send the POST twice. State held only in those instances goes with them, including, on Windows, files in %SystemDrive%\local, "not persistent across app restarts" (operating system functionality).
Work that runs without a request
A staging slot is a live app, and Microsoft's pages assume its background work runs whether or not anyone is testing it.
- WebJobs. A continuous WebJob "Runs on all instances that the web app runs on". The remedy is
WEBJOBS_STOPPED=1, "to prevent conflicting WebJobs from running both in staging and production slots", orWEBJOBS_DISABLE_SCHEDULE=1for triggered ones, marked as a slot setting (WebJobs). - Timer functions. "It's common to disable timer triggered functions in slots to prevent simultaneous executions", with
AzureWebJobs.<FUNCTION_NAME>.Disabledas a slot setting (disable functions). Our reading of why the timer's single-run lock does not help: it is a storage lock tied to the app's identifying configuration (timer trigger), and two slots sharing that identity and a storage account are a host ID collision, which stops the host in version 4.x (storage considerations). In any working configuration, each slot holds its own lock. - Queue and event triggers. "Deployment slot swaps work best with HTTP and webhook triggers"; for queues or Event Hubs, the trigger should take its definition from an app setting that changes with the swap (Durable Functions versioning).
- Orchestrations in flight. A breaking change makes running orchestrations fail, "especially a problem for long-running orchestrations". Microsoft's slot-based strategy swaps only "After all orchestration instances are complete", behind a pipeline gate (zero-downtime deployment for Durable Functions).
The interval in the middle. The swap's first step gives the staging slot production's slot settings, and a swap with preview pauses there until it is completed or cancelled (staging environments, above). Our reading: from that restart until the routing switch, the new version runs with production's slot settings beside the old one. If both slots define a setting that disables a timer or a WebJob, as Microsoft advises, staging takes production's value, the one that lets it run, and a trigger whose connection is a slot setting reads production's queue. Cancelling reapplies configuration; it does not undo what was processed. A preview is a partial release.
The data the new version wrote
Both of Microsoft's lists are lists of configuration; neither includes a database, a queue or the data the application wrote. The rollback restores "the slots to their pre-swap states" (staging environments, above). Our reading: a swap back after the new version changed a schema, wrote rows in a new shape or queued messages the old consumers cannot parse puts the old code in front of data it has never seen.
Microsoft's guidance for a service that cannot stop draws the line in the same place. Binaries roll back, but "Once databases are upgraded, the service is in a roll-forward situation if a problem occurs", since "if the upgrade fails, then the rollback would likely fail as well". Its binaries understand schema versions "N and N-1", and the database is changed only "If the binary deployment succeeds" (Eliminate downtime through versioned service updates). Our reading for slots: swapping back is a rollback for as long as the old version can read everything the new one can write, and no longer.
What we recommend, in order
These are our recommendations, not Microsoft's.
- Decide every setting: the environment's, marked as a slot setting in every slot, or the version's, left to swap. Read the swap dialog's source and target changes before each swap.
- Silence non-production slots. Stop WebJobs, disable timers and point triggers at non-production sources, all with slot settings, and keep previews short: the swap's first step gives staging production's values of all three.
- Make the warm-up a gate: an endpoint that checks what the version depends on, only success codes accepted, and logs that show the requests arrived.
- Drain what the swap would kill. Move long work to queues with idempotent consumers, keep requests short, and swap Durable Functions only when nothing is running, or use orchestration versioning.
- Separate the schema from the swap. Swap in code that works with the current and the next schema, change the database once the swap has held, then roll forward.
- Grant production's identity new permissions a day before the swap.
- Rehearse on non-production slots. Swap while a long request, a timer and a queue consumer run, swap back, and count what finished, what ran twice and what the old version could not read.
- Where Functions must not drop executions, consider Flex Consumption with rolling updates, on its terms: changes "must be backward compatible", and "There's currently no feature to roll back a site update" (site update strategies, above).
What this does not settle
- What happens to a request in flight at the moment of the switch, and how long the former production instances serve before they are recycled. Microsoft does not document either.
- Whether custom warm-up runs on a manual swap. The step list opens it with "If auto swap is enabled with custom warm-up"; elsewhere the page says, unconditionally, that "The swap operation waits for this custom warm-up to finish" (staging environments, above). A test swap's logs settle it.
- Whether hybrid connections, service endpoints and the content delivery network swap. The App Service page lists them as swapped; the Functions page says they "don't get swapped, by design" (both above).
- What a slot setting defined in only one slot does during a swap. Microsoft advises defining it everywhere and does not describe the alternative.
- Whether files written at runtime to the content share follow the swap.
%HOME%is a share "dedicated for that app" (operating system functionality, above); the swap pages do not address runtime writes.
Where this fits
- A retry that sends a POST twice is an abandoned request seen from the client: a lost response, and a second write unless the create carries a key.
- Writing to two systems is not a transaction quotes the same limit for a migration: once the old structures are gone, going back means you "must restore those objects and replay data changes". A swap back reaches it at the database.
- Installing a SharePoint Server Subscription Edition update without downtime draws the same line for a farm: zero downtime keeps people working, and "The procedure is a way forward."
- The API an integration can call after it moves to .NET 10: released through a slot, such an integration takes its .NET version with the code, but not its managed identity.
- The three decisions you make before moving to Azure warns that a decision not taken gets "made by default". Which settings stay with a slot is one, and a Functions staging slot created in the portal starts with all of production's.
Sources, checked on 7 November 2026
- Azure App Service: Set up staging environments in Azure App Service, Deployment best practices, Run background tasks with WebJobs, Use managed identities for App Service and Azure Functions, Operating system functionality in Azure App Service
- Azure Functions: Azure Functions deployment slots, How to disable functions in Azure Functions, Timer trigger for Azure Functions, Storage considerations for Azure Functions, Improve the performance and reliability of Azure Functions, Migrate apps from Azure Functions version 3.x to version 4.x, Site update strategies in Flex Consumption
- Durable Functions: Zero-downtime deployment for Durable Functions, Versioning challenges and mitigation strategies in Durable Functions
- Azure DevOps: Eliminate downtime through versioned service updates
Support independent engineering knowledge
Knowledge, Analysis, the Field Guide and the tools are free to read and use, and they stay that way. If this article saved you time, you can support the research and writing behind it. Support is voluntary and unlocks nothing.
Buy me a coffee (opens in a new tab)João Lívio's page on buymeacoffee.com