Application Initialization (AppInit) is an IIS module built into Azure App Service (Windows) that triggers application warm-up before instances begin serving production traffic.
Without it, the first request after a restart, scale-out, or slot swap absorbs the full cold-start penalty: JIT compilation, cache priming, EF model building, and connection pool establishment. AppInit eliminates that penalty by warming instances before traffic is routed to them.
NOTE
AppInit is available for Windows-based App Service plans (Basic and above). It is not natively supported on Linux. For Linux plans, use the WEBSITE_WARMUP_PATH app setting combined with a Health Check endpoint instead.
How Application Initialization Works
When App Service brings an instance online — on restart, scale-out, or slot swap — the following sequence occurs:
The worker process (w3wp.exe) starts on the target instance.
IIS reads the applicationInitialization block from web.config and issues internal HTTP requests to each configured initializationPage.
These requests are internal — they bypass external ingress (Front Door, App Gateway) and are not recorded in standard IIS access logs.
App Service holds traffic for this instance and waits for a valid HTTP response.
Once all instances return a valid response, traffic is routed (or the slot swap completes). This behavior is deterministic — App Service does not route traffic until warm-up is confirmed on all instances.
The 10-Minute Startup Window
App Service guarantees each instance at least 10 minutes to start and respond before traffic is forced to it. When AppInit is configured and responding, the platform (known internally as AppInit Empathy) can extend this window up to 30 minutes for longer initialization workloads. Design your warm-up to complete well within 10 minutes. At scale, unlikely combinations of events will eventually occur.
What App Service Validates — and What It Does Not
This is the most important distinction when designing a warm-up strategy:
Layer
Responsibility
Owner
Azure App Service
Instance startup, warm-up request triggering, traffic routing, enforcing status code rules via WEBSITE_SWAP_WARMUP_PING_STATUSES
Microsoft
IIS (Runtime)
Sends internal HTTP requests to configured initializationPage endpoints per web.config
App Service / IIS
Your Application
Warm-up endpoints block until dependencies are ready; return correct status codes that reflect true readiness
You
WARN
App Service validates HTTP responsiveness — it does not introspect your application state. If your warm-up endpoint returns HTTP 200 before databases, caches, or downstream services are ready, App Service considers the instance warm. The platform does exactly what you configure it to do. Endpoint design is your responsibility.
By default, any HTTP response is treated as a successful warm-up. To enforce stricter validation during slot swaps, set WEBSITE_SWAP_WARMUP_PING_STATUSES to a comma-separated list of acceptable codes (e.g., 200). The swap aborts if a non-listed code is received.
IIS-Level vs Platform-Level Warm-Up: How They Stack
There are two distinct warm-up mechanisms in App Service. They are complementary — they stack, not compete. Understanding which fires when is critical for correct configuration.
Mechanism
Configured In
Fires On
OS
applicationInitialization (web.config)
web.config <system.webServer>
Every restart, scale-out, slot swap
Windows only
WEBSITE_WARMUP_PATH
App Settings
Every site restart
Windows + Linux
WEBSITE_SWAP_WARMUP_PING_PATH
App Settings
Slot swaps only — additional platform ping
Windows + Linux
WEBSITE_SWAP_WARMUP_PING_STATUSES
App Settings
Slot swaps only — enforces valid response codes
Windows + Linux
During a slot swap with web.config AppInit configured: IIS fires the applicationInitialization warm-up AND App Service fires the platform-level WEBSITE_SWAP_WARMUP_PING_PATH ping (if set). Both must succeed. The swap completes only after all instances on the source slot are confirmed warm.
NOTE
WEBSITE_SWAP_WARMUP_PING_PATH only applies during slot swaps. WEBSITE_WARMUP_PATH applies on every restart. If you only configure WEBSITE_SWAP_WARMUP_PING_PATH, restarts outside of swaps will not trigger a platform-level warm-up ping.
Prerequisites
Windows-based App Service plan (Basic tier or higher)
Always On enabled — required for non-slot scenarios to prevent idle app pool unloading
Access to edit the application web.config
At least one HTTP readiness endpoint that blocks until the application is truly ready
For slot scenarios: a deployment slot configured in the Azure Portal
Step 1 — Create a True Readiness Endpoint
Your warm-up endpoint must block until initialization is complete before returning HTTP 200. An endpoint that returns 200 immediately provides no warm-up benefit — App Service will route traffic to an instance that looks warm but is not ready.
ASP.NET Core Example
// Program.cs — blocks until the host signals ApplicationStarted app.MapGet(“/warmup”, async (IHostApplicationLifetime lifetime) => { var tcs = new TaskCompletionSource(); lifetime.ApplicationStarted.Register(() => tcs.SetResult()); await tcs.Task; return Results.Ok(new { status = “ready”, timestamp = DateTime.UtcNow }); });
ASP.NET Framework Example
// Global.asax.cs — prime dependencies in Application_Start protected void Application_Start() { EntityFrameworkConfig.Initialize(); // build EF models CacheService.Prime(); // warm memory cache Application[“AppReady”] = true; } // WarmupController.cs public ActionResult Index() { // Return 503 during startup to keep instance out of rotation if (Application[“AppReady”] as bool? != true) return new HttpStatusCodeResult(503); return Content(“ready”); }
TIP
Return HTTP 200 only when your application is genuinely ready — databases connected, caches warm, downstream dependencies reachable. Using HTTP 503 during initialization keeps the instance out of rotation and gives you a clean, observable signal that warm-up is still in progress.
Step 2 — Configure web.config
Add the applicationInitialization element inside <system.webServer> in your web.config. Multiple initialization pages can be defined; IIS pings each in order.
<applicationInitialization doAppInitAfterRestart=”true”> <!– Signal full dependency readiness –> <add initializationPage=”/warmup” hostName=”[your-app].azurewebsites.net” /> <!– Pre-load a heavy API surface –> <add initializationPage=”/api/health” hostName=”[your-app].azurewebsites.net” /> </applicationInitialization>
Key Attribute Reference
Attribute
Default
Description
doAppInitAfterRestart
false
Set to true. Ensures initialization fires on every app restart. Without this, AppInit only runs on first-load after deployment.
skipManagedModules
false
Set to false for full .NET initialization. Set to true only for static or unmanaged apps that do not need ASP.NET modules loaded during warm-up.
remapManagedRequestsTo
(none)
Optional path to a static HTML splash page shown to users while warm-up is in progress. Requires URL Rewrite module for complex mappings.
initializationPage
(required)
Relative URL path for IIS to ping internally. Must return a valid HTTP response to signal readiness.
hostName
(optional)
Hostname used in the internal warm-up request. Match the app’s .azurewebsites.net hostname.
WARN
AppInit warm-up requests travel via HTTP internally, not HTTPS. URL rewrite rules that redirect HTTP to HTTPS (301) will intercept warm-up requests before they reach your application code, causing AppInit to fail silently. Exclude your warm-up path from HTTPS redirect rules.
Step 3 — Enable Always On
With Always On disabled (the default), IIS unloads the application pool after 20 minutes of inactivity. The next request triggers a full cold start regardless of AppInit configuration. Always On instructs the front-end load balancer to send a GET request to the app root every 5 minutes, keeping the process alive.
Enable via Azure Portal
Navigate to your App Service in the Azure Portal.
Select Settings > Configuration > General settings.
Set Always On to On.
Click Save and confirm the restart.
Enable via Azure CLI
az webapp config set \ –resource-group <resource-group> \ –name <app-name> \ –always-on true
These app settings operate at the App Service platform layer above IIS. They complement the web.config applicationInitialization configuration. Use them to cover Linux slots, cross-restart warm-up, and to enforce strict status code validation during slot swaps.
App Setting
Example
Fires On
Description
WEBSITE_WARMUP_PATH
/warmup
Every site restart
Platform-level path to ping on any restart. Works on both Windows and Linux. Recommended complement to web.config AppInit.
WEBSITE_SWAP_WARMUP_PING_PATH
/warmup
Slot swaps only
Additional platform-level path pinged during slot swaps. Stacks on top of IIS-level AppInit warm-up.
WEBSITE_SWAP_WARMUP_PING_STATUSES
200
Slot swaps only
Comma-separated valid HTTP status codes for swap warm-up validation. Swap aborts if response code is not in this list. Default accepts any HTTP response.
Step 5 — Verify with Failed Request Tracing (FREB)
Warm-up requests are not recorded in standard IIS access logs. The only reliable verification method is Failed Request Tracing (FREB). Look for requests with User-Agent IIS Application Initialization Warmup and inspect the HTTP status code returned.
Exclude warm-up path from HTTPS redirect rules. For long-running init, use Swap with Preview to extend the warm-up window before committing.
Cold starts still occur after AppInit configured
doAppInitAfterRestart not set to true, or Always On is disabled
Set doAppInitAfterRestart=”true” in web.config. Enable Always On under Configuration > General settings.
AppInit does not appear to fire
Misconfigured web.config, or initializationPage returning non-200
Validate with FREB. Confirm warm-up path is not intercepted by URL rewrite rules.
Linux app not warming up
applicationInitialization is Windows/IIS only
Use WEBSITE_WARMUP_PATH app setting. Pair with Health Check for instance-level monitoring.
Swap timing out on large initialization workload
App startup exceeds the default swap wait window
Use Swap with Preview (multi-phase swap) in the Azure Portal to manually control and extend the warm-up window before committing the swap.
Warm-up requests invisible in IIS logs
Expected behavior — AppInit bypasses standard IIS logging
Use FREB tracing. Filter for User-Agent: IIS Application Initialization Warmup in the trace XML.
The Complete Mental Model
Application Initialization in Azure App Service spans three layers. All three must be correctly configured for warm-up to be functionally meaningful.
Layer
What It Does
What It Cannot Do
Azure App Service
Holds traffic, triggers warm-up pings, enforces status code rules via WEBSITE_SWAP_WARMUP_PING_STATUSES, routes traffic only after readiness is confirmed on all instances
Inspect application state, verify database connections, or validate that your business logic is fully operational
IIS (Runtime)
Sends internal HTTP requests to configured initializationPage endpoints per web.config before routing traffic to the worker process
Determine whether your application code ran successfully or whether dependencies are actually available
Your Application
Blocks the warm-up response until startup is complete; surfaces true readiness as HTTP 200; returns 503 during initialization
Force App Service to wait without a properly implemented blocking endpoint
KEY
A warm instance is not automatically a ready instance. App Service confirms HTTP responsiveness — your code must ensure that HTTP responsiveness and application readiness are the same thing. If they are not aligned, warm-up succeeds technically but fails functionally.
Quick Reference
Configuration
Fires On
Scope
OS
web.config applicationInitialization
Every restart, scale-out, slot swap
IIS-level, per worker process
Windows only
WEBSITE_WARMUP_PATH
Every site restart
Platform-level ping
Windows + Linux
WEBSITE_SWAP_WARMUP_PING_PATH
Slot swaps only
Additional platform swap ping
Windows + Linux
WEBSITE_SWAP_WARMUP_PING_STATUSES
Slot swaps only
Enforces valid HTTP response codes
Windows + Linux
Always On
Continuous (idle prevention)
Keeps app pool alive, prevents 20-min unload
Windows
Reference Articles
Set Up Staging Environments (Custom Warm-Up) — learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots
Routine Maintenance, Restarts, and Downtime — learn.microsoft.com/en-us/azure/app-service/routine-maintenance-downtime
Configure an App Service App (Always On) — learn.microsoft.com/en-us/azure/app-service/configure-common
Monitor App Service Instances with Health Check — learn.microsoft.com/en-us/azure/app-service/monitor-instances-health-check
App Service Warm-Up Demystified (AppInit Empathy, 10-min window) — michaelcandido.com/app-service-warm-up-demystified