{"id":799,"date":"2026-09-27T02:41:13","date_gmt":"2026-09-27T02:41:13","guid":{"rendered":"https:\/\/windows-vps.org\/blog\/?p=799"},"modified":"2026-09-27T02:41:13","modified_gmt":"2026-09-27T02:41:13","slug":"iis-application-initialization-warmup-windows-server","status":"publish","type":"post","link":"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/","title":{"rendered":"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The first request to an ASP.NET application after an IIS restart is always the slowest. Application pool recycling, a server reboot, or a config change forces the worker process to recompile assemblies and warm caches, and that first user pays the entire cost \u2014 often five to thirty seconds of spinner. Application Initialization, built into IIS 8 and later, lets the server do that work before it accepts traffic.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">When this matters (and when it does not)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If your application recycles nightly, if you deploy frequently, or if you run more than one node behind a load balancer, warmup turns a user-visible freeze into a background task. For a single long-running app pool that recycles weekly, the payoff is smaller but the setup cost is near zero, so there is little reason to skip it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Install the feature and confirm the module<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The role service is called <em>Application Initialization<\/em>. Install it in an elevated PowerShell session:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Install-WindowsFeature Web-AppInit\n\n# verify it loaded\nGet-WebGlobalModule | Where-Object Name -eq 'ApplicationInitializationModule'<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you manage IIS with the Configuration Editor rather than feature management, the module appears under <code>system.webServer\/applicationInitialization<\/code> at the server level.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Enable preload on the application and the pool<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Two switches must both be set: the application must be marked for preload, and the pool must start automatically. Missing either one silently disables the whole mechanism.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Import-Module WebAdministration\n\nSet-ItemProperty IIS:\\Sites\\MyApp -Name applicationDefaults.preloadEnabled -Value $true\nSet-ItemProperty IIS:\\AppPools\\MyApp -Name startMode -Value AlwaysRunning\nSet-ItemProperty IIS:\\AppPools\\MyApp -Name processModel.idleTimeout -Value \"00:00:00\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Setting <code>idleTimeout<\/code> to zero stops IIS from unloading the worker process after twenty minutes of inactivity. Combined with <code>AlwaysRunning<\/code>, the app stays resident and warm between requests.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Declare a warmup URL<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Preload alone starts the process; it does not exercise the application. Add a <code>web.config<\/code> entry pointing at a lightweight endpoint that touches the expensive paths without doing real work.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;system.webServer&gt;\n  &lt;applicationInitialization doAppInitAfterRestart=\"true\"&gt;\n    &lt;add initializationPage=\"\/warmup\" \/&gt;\n    &lt;add initializationPage=\"\/health\/db\" \/&gt;\n  &lt;\/applicationInitialization&gt;\n&lt;\/system.webServer&gt;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">IIS will not route traffic to the site until those pages return a successful status. Design <code>\/warmup<\/code> to prime the things that are actually slow: JIT-compile controller types, open the database connection pool, load configuration, and populate any in-memory cache.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Warmup target<\/th><th>Why it helps<\/th><th>Cost<\/th><\/tr><\/thead><tbody><tr><td>Razor\/compiled views<\/td><td>First render is fast<\/td><td>Low<\/td><\/tr><tr><td>DB connection pool<\/td><td>First query does not pay handshake<\/td><td>Low<\/td><\/tr><tr><td>In-memory cache<\/td><td>Avoids cold-start stampede<\/td><td>Medium<\/td><\/tr><tr><td>External API clients<\/td><td>DNS and TLS warm<\/td><td>Medium<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Do not slow down deployment<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There is a tradeoff to respect: IIS now waits for your warmup pages before serving traffic, so a slow warmup becomes deployment latency. Keep warmup endpoints fast and idempotent, and cap their runtime at a few seconds. If warmup fails, IIS retries rather than serving a cold site \u2014 consider that a feature, but monitor the failed-request log so a broken warmup endpoint does not look like an outage.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Multi-node and load-balanced deployments<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Warmup matters most when more than one node serves traffic. Without it, a rolling deployment or a pool recycle on one node sends that node&#8217;s share of requests into a cold app while its peers are already warm \u2014 the imbalance shows up as a latency spike that looks like a network problem. With preload enabled on every node, the load balancer only needs a health probe that respects the same warmup endpoint.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Deployment style<\/th><th>Cold-start exposure<\/th><th>Warmup value<\/th><\/tr><\/thead><tbody><tr><td>Single node, weekly recycle<\/td><td>One window<\/td><td>Moderate<\/td><\/tr><tr><td>Rolling deploy, 2+ nodes<\/td><td>Per-node spike<\/td><td>High<\/td><\/tr><tr><td>Autoscaling instances<\/td><td>Every scale-out<\/td><td>Very high<\/td><\/tr><tr><td>Blue\/green swap<\/td><td>On cutover<\/td><td>High<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Interaction with recycle settings<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Application Initialization does not override the recycle schedule \u2014 it complements it. Leave a scheduled recycle in place for the memory-reclamation benefit, but pair it with overlapping recycle so a new worker process starts and warms before the old one retires. Check the pool&#8217;s <em>Disable Overlapped Recycle<\/em> setting is off:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Get-ItemProperty IIS:\\AppPools\\MyApp `\n    -Name recycling.disallowOverlappingRotation\n# Value should be False; set it explicitly if it is not\nSet-ItemProperty IIS:\\AppPools\\MyApp `\n    -Name recycling.disallowOverlappingRotation -Value $false<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Overlapped recycle combined with a warmup page means users never touch a cold process, even during a scheduled recycle. This single pairing eliminates the most common &#8220;the site is slow every night at 3am&#8221; complaint.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common pitfalls that silently break warmup<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Warmup page returns a redirect.<\/strong> IIS follows redirects for initialization pages in some configurations; a warmup URL that 302s to the login page may never warm the real code path. Return 200 directly.<\/li>\n<li><strong>Preload enabled but pool start mode left on OnDemand.<\/strong> The process still stops, and the next request is cold again.<\/li>\n<li><strong>Warmup page depends on an external service that is also cold.<\/strong> Chain the warmup so the DB ping happens before the cache fill, not in parallel.<\/li>\n<li><strong>Application Initialization installed but web.config not deployed.<\/strong> The module does nothing without the <code>applicationInitialization<\/code> section.<\/li>\n<li><strong>Health probes configured to ignore warmup.<\/strong> A probe that returns healthy before warmup completes routes traffic to a cold process anyway.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Each of these produces the same symptom \u2014 a first request that is still slow \u2014 so work through the list in order when warmup appears not to work.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verify it worked<\/h2>\n\n\n\n<ol class=\"wp-block-list\"><li>Recycle the pool: <code>Restart-WebAppPool -Name MyApp<\/code><\/li>\n<li>Immediately time a request to a heavy page \u2014 it should already be warm.<\/li>\n<li>Check <code>%SystemDrive%\\inetpub\\logs\\LogFiles<\/code> for the warmup hits before any user request.<\/li>\n<li>Confirm the pool process is running with no request: <code>Get-Process w3wp<\/code> should show it resident.<\/li><\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Set up correctly, Application Initialization removes the cold-start penalty entirely and makes deployments invisible to users instead of a brief outage. It is one of the highest-value ten-minute IIS changes available, particularly on VPS deployments that lack the spare capacity to absorb a stampede of cold requests.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The first request to an ASP.NET application after an IIS restart is always the slowest. Application pool recycling, a server reboot, or a config change forces the worker process to recompile assemblies and warm caches, and that first user pays the entire cost \u2014 often five to thirty seconds of spinner. Application Initialization, built into &#8230; <a title=\"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles\" class=\"read-more\" href=\"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/\" aria-label=\"Read more about IIS Application Initialization: Warming Up ASP.NET Apps After Recycles\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":3,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-799","post","type-post","status-publish","format-standard","hentry","category-reviews"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>IIS Application Initialization: Warming Up ASP.NET Apps After Recycles - Windows VPS Blog<\/title>\n<meta name=\"description\" content=\"The first request to an ASP.NET application after an IIS restart is always the slowest. Application pool recycling, a server reboot, or a config change\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles\" \/>\n<meta property=\"og:description\" content=\"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles\" \/>\n<meta property=\"og:url\" content=\"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/\" \/>\n<meta property=\"og:site_name\" content=\"Windows VPS Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-27T02:41:13+00:00\" \/>\n<meta name=\"author\" content=\"windows-vps\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@myxiechengxuan\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"windows-vps\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/\",\"url\":\"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/\",\"name\":\"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles - Windows VPS Blog\",\"isPartOf\":{\"@id\":\"https:\/\/windows-vps.org\/blog\/#website\"},\"datePublished\":\"2026-09-27T02:41:13+00:00\",\"author\":{\"@id\":\"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/44caceed916d0db318aa08d5623a7a58\"},\"description\":\"The first request to an ASP.NET application after an IIS restart is always the slowest. Application pool recycling, a server reboot, or a config change\",\"breadcrumb\":{\"@id\":\"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/windows-vps.org\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/windows-vps.org\/blog\/#website\",\"url\":\"https:\/\/windows-vps.org\/blog\/\",\"name\":\"Windows VPS Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/windows-vps.org\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/44caceed916d0db318aa08d5623a7a58\",\"name\":\"windows-vps\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/3f2573db5afcd1a6ab9abcc5d48fc8e42584bc87ab9d98cc156e5b2097766dd9?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/3f2573db5afcd1a6ab9abcc5d48fc8e42584bc87ab9d98cc156e5b2097766dd9?s=96&d=mm&r=g\",\"caption\":\"windows-vps\"},\"sameAs\":[\"https:\/\/windows-vps.org\/blog\",\"https:\/\/x.com\/myxiechengxuan\"],\"url\":\"https:\/\/windows-vps.org\/blog\/author\/myxiechengxuan\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles - Windows VPS Blog","description":"The first request to an ASP.NET application after an IIS restart is always the slowest. Application pool recycling, a server reboot, or a config change","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/","og_locale":"en_US","og_type":"article","og_title":"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles","og_description":"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles","og_url":"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/","og_site_name":"Windows VPS Blog","article_published_time":"2026-09-27T02:41:13+00:00","author":"windows-vps","twitter_card":"summary_large_image","twitter_creator":"@myxiechengxuan","twitter_misc":{"Written by":"windows-vps","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/","url":"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/","name":"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles - Windows VPS Blog","isPartOf":{"@id":"https:\/\/windows-vps.org\/blog\/#website"},"datePublished":"2026-09-27T02:41:13+00:00","author":{"@id":"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/44caceed916d0db318aa08d5623a7a58"},"description":"The first request to an ASP.NET application after an IIS restart is always the slowest. Application pool recycling, a server reboot, or a config change","breadcrumb":{"@id":"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/windows-vps.org\/blog\/iis-application-initialization-warmup-windows-server\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/windows-vps.org\/blog\/"},{"@type":"ListItem","position":2,"name":"IIS Application Initialization: Warming Up ASP.NET Apps After Recycles"}]},{"@type":"WebSite","@id":"https:\/\/windows-vps.org\/blog\/#website","url":"https:\/\/windows-vps.org\/blog\/","name":"Windows VPS Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/windows-vps.org\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/44caceed916d0db318aa08d5623a7a58","name":"windows-vps","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/windows-vps.org\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/3f2573db5afcd1a6ab9abcc5d48fc8e42584bc87ab9d98cc156e5b2097766dd9?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/3f2573db5afcd1a6ab9abcc5d48fc8e42584bc87ab9d98cc156e5b2097766dd9?s=96&d=mm&r=g","caption":"windows-vps"},"sameAs":["https:\/\/windows-vps.org\/blog","https:\/\/x.com\/myxiechengxuan"],"url":"https:\/\/windows-vps.org\/blog\/author\/myxiechengxuan\/"}]}},"_links":{"self":[{"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/posts\/799","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/comments?post=799"}],"version-history":[{"count":1,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/posts\/799\/revisions"}],"predecessor-version":[{"id":804,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/posts\/799\/revisions\/804"}],"wp:attachment":[{"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/media?parent=799"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/categories?post=799"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/windows-vps.org\/blog\/wp-json\/wp\/v2\/tags?post=799"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}