ASP.NET Web Apps Errors, 5xx, Cold Start, Deployment, and Config Fixes
Why ASP.NET Web Apps Errors Keep Hitting You
You deploy your ASP.NET application, everything looks fine in staging, and then, boom. A 503 Service Unavailable greets your users on production. Or the app takes 45 seconds to respond after the first request of the day. Or a configuration change you made in web.config silently kills the application pool with no clear error message. I've seen this exact chain of events on dozens of production servers, and I know how demoralizing it is when you can't tell whether the problem is your code, IIS, the .NET runtime, or something else entirely.
ASP.NET Web Apps errors are uniquely frustrating because they sit at the intersection of several moving parts: the .NET runtime, IIS, the Windows file system, application configuration, and, often overlooked, antivirus software running on the same host. When any one of these layers misbehaves, the symptoms surface as generic HTTP 5xx errors or silent application recycling events that leave no obvious breadcrumbs.
The root causes fall into a handful of patterns. The most common one? The ASP.NET AppDomain gets unloaded unexpectedly. This happens because ASP.NET actively monitors dozens of files and directories using a Windows API called ReadDirectoryChangesW. The moment anything in a watched folder changes, a file rename, a size difference, an ACL modification, IIS tears down the AppDomain and rebuilds it from scratch. That's a cold start, and cold starts cause those slow first requests and occasional 503s that users blame on "the server acting up."
Antivirus software is one of the biggest silent culprits here. When an antivirus engine scans the bin, App_Code, Temporary ASP.NET Files, or any other monitored directory, it triggers file system events that ASP.NET interprets as legitimate changes. The runtime doesn't know it was just a scan, it sees a modification event and recycles the AppDomain. This produces performance spikes, unexpected 503s, and event log entries that look like application crashes when they're actually false-positive recycling events.
Beyond antivirus, ASP.NET Web Apps errors during deployment usually trace back to web.config problems, a malformed XML element, a missing connection string, a permissions issue on the configuration directory, or a parent application's config file changing in a way that cascades down. Cold start issues often come from applications not being warmed up after a recycle, or from FCN (File Change Notification) mode being too aggressive.
The good news: every one of these problems has a clear, documented fix. This guide walks you through all of them, from the fastest one-liner solution to the deeper configuration changes that will make your ASP.NET application rock-solid under real production load. Browse all Microsoft fix guides →
The Quick Fix, Try This First for ASP.NET Web Apps Errors
Before you go deep into IIS configuration or event log archaeology, there's one fix that resolves the majority of unexpected AppDomain recycling and cold start performance issues on Windows servers: exclude your ASP.NET application directories from antivirus scanning.
This single change has fixed the problem for more production servers than I can count. Antivirus real-time scanning hooks into the same file system notification API that ASP.NET uses. Every time the scanner touches a file in your application's directory tree, ASP.NET sees it as a change and reacts accordingly, recycling the AppDomain, triggering a cold start, and potentially returning a 503 to users in the middle of that recycle window.
Here's exactly what to exclude in your antivirus or endpoint protection software (Windows Defender, Trend Micro, CrowdStrike, the exclusion process varies, but the paths are the same):
- The root directory of your ASP.NET application and all subdirectories beneath it
- The Temporary ASP.NET Files folder, typically at
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\(the exact path varies based on your .NET Framework version and whether your app pool runs 32-bit or 64-bit) - The .NET Framework config directory, varies by version and bitness
- The root directory of the parent application if your app is a sub-application
- The IIS-specific paths:
%systemroot%\System32\inetsrv\configand%systemdrive%\inetpub\temp
After adding these exclusions, do a manual IIS reset (iisreset /noforce from an elevated command prompt) and monitor your application's Event Log for the next 30 minutes. In most cases, you'll see the AppDomain recycling events stop entirely, and your cold-start latency will drop dramatically.
If the problem persists after antivirus exclusions, move on to the step-by-step section below, the issue likely lives in your configuration or deployment pipeline.
Before touching any configuration, you need to know what you're actually fixing. The Windows Event Viewer is your primary diagnostic tool for ASP.NET Web Apps errors, not the browser's 500 error page, which almost never tells you anything useful in production.
Open Event Viewer by pressing Win + R, typing eventvwr.msc, and hitting Enter. Navigate to Windows Logs → Application. Filter the log by source, look for entries from ASP.NET 4.0.30319.0 (or whichever version you're running) and W3SVC-WP.
The event IDs to watch for:
- Event ID 1309, An unhandled exception occurred. This gives you the actual .NET exception type and stack trace.
- Event ID 1325, An AppDomain was unloaded. Look at the reason field, it tells you whether the unload was triggered by a file change, a config change, or a timeout.
- Event ID 2276, Worker process shutdown due to application pool recycling.
If you see Event ID 1325 with a reason mentioning file change notifications, that's your antivirus or deployment process touching monitored directories. If you see Event ID 1309 with a ConfigurationErrorsException, your web.config has a syntax error or references a missing assembly. Make a note of the exact timestamp and error, you'll need it in the next steps.
For ASP.NET Core applications running on Linux or in Azure App Service, the equivalent is Application Insights or the Kudu diagnostic console, but the underlying causes are the same.
I cannot stress this enough: back up your configuration files before you touch anything. I've watched developers fix one problem and create three new ones because they made changes to web.config without a restore point. Recovery from a broken IIS configuration without a backup is hours of work, with a backup, it's two minutes.
ASP.NET applications running on IIS 7.0 and later store both ASP.NET and IIS settings in the same web.config files. The ASP.NET settings live under the <system.web> section; IIS settings live under <system.webServer>. Both matter, and breaking either section breaks the application.
The master IIS configuration file, applicationHost.config, is stored at %systemroot%\System32\inetsrv\config\. Back it up first using the built-in AppCmd tool from an elevated command prompt:
%systemroot%\system32\inetsrv\APPCMD add backup MyBackup
This creates a timestamped backup of the entire IIS configuration that you can restore instantly if something goes wrong. To restore it later:
%systemroot%\system32\inetsrv\APPCMD restore backup MyBackup
For your application's individual web.config files, use the IIS Configuration Editor (available in IIS Manager under your site's Management section) to see all configuration file locations. Then copy each one to a backup directory with a date stamp in the filename before editing. A five-second copy operation can save you hours of recovery work.
Once your backups are in place, you can make changes confidently. If you see the application fail immediately after a config edit, restore from backup and start fresh, don't try to manually undo changes in a broken state.
ASP.NET uses the ReadDirectoryChangesW Win32 API to monitor your application's file system. This is how it detects legitimate changes, like a new DLL in the bin folder after a deployment, and applies them by recycling the AppDomain. The problem is that this same mechanism fires on any file system event, including ones caused by antivirus scans, backup agents, and search indexers.
ASP.NET monitors these specific directories and files for changes:
- The application's physical root path and all subdirectories, for subdirectory name changes or deletions
bin,App_Code,App_WebReferences,App_GlobalResources, andApp_Browsers, for creation, deletion, renaming, ACL changes, last-write time changes, and size changesmachine.configand rootweb.config, any change here unloads every ASP.NET AppDomain on the machine- Parent application
web.configfiles - The application's own
web.config - The
hash.webfile in theTemporary ASP.NET Fileshash subdirectory - Any
web.configin any subdirectory of the application App_LocalResourcessubdirectories in each virtual subdirectory
Configure your antivirus or backup software to exclude all of these paths. In Windows Defender, open Windows Security → Virus & threat protection → Virus & threat protection settings → Exclusions → Add or remove exclusions. Add each path as a "Folder" exclusion, not a file exclusion, so it covers all contents recursively.
After saving exclusions, verify the change took effect by running a quick scan on the excluded folder manually, it should complete instantly without triggering any file modification events visible in Process Monitor.
Cold starts in ASP.NET Web Apps are a direct consequence of AppDomain recycling, whether triggered by a file change notification, a scheduled IIS recycle, or an application pool idle timeout. When the AppDomain is torn down and rebuilt, the first request hits the full JIT compilation and initialization chain. On a complex application, that can mean 10–60 seconds of perceived unresponsiveness.
The fastest fix for scheduled recycles is to configure IIS Application Initialization (available in IIS 8.0 and later). In IIS Manager, navigate to your site, open Application Initialization, and set the Start Mode of your application pool to AlwaysRunning. This keeps the worker process alive even when no requests are coming in.
Next, add an initialization page to your web.config so IIS can warm up the application before serving real user traffic:
<system.webServer>
<applicationInitialization
doAppInitAfterRestart="true"
skipManagedModules="false">
<add initializationPage="/health" />
</applicationInitialization>
</system.webServer>
Replace /health with any lightweight endpoint in your application that forces the full initialization stack to run, a health check endpoint is ideal. IIS will hit this URL after every recycle before returning the worker process to the load rotation.
Also check your application pool's Idle Time-out setting. By default, IIS shuts down a worker process after 20 minutes of inactivity. For applications that get sporadic traffic, this means every hour or so you'll hit a cold start. Set it to 0 (disabled) for production workloads where warm response times matter, or increase the timeout to match your typical traffic gap.
You should see warm first-request times after these changes. Verify by hitting the application immediately after an iisreset and watching the response time drop compared to before.
If your ASP.NET application exposes ASMX web services, there's a configuration issue that often causes both security warnings and unexpected behavior in production: the documentation protocol being left enabled. When a browser hits an ASMX service endpoint with no parameters, ASP.NET automatically generates an HTML documentation page describing every operation, every parameter, and every data type your service accepts. This is useful during development, and a liability in production.
More importantly, leaving this enabled can trigger automated security scanners that flag it as an information disclosure vulnerability, sometimes resulting in 403 responses from a WAF that blocks the endpoint entirely, which surfaces as a 5xx error from the application's perspective.
To disable the documentation protocol, open your application's web.config in a text editor and add the following inside the <system.web> block:
<webServices>
<protocols>
<remove name="Documentation" />
</protocols>
</webServices>
Save the file and the change takes effect immediately, you don't need to restart IIS. Test by browsing directly to your .asmx endpoint in a browser. You should now see a plain-text or error response instead of the formatted documentation page. This doesn't break any SOAP or REST clients, it only removes the browser-facing documentation layer.
While you have web.config open, this is also a good time to validate the entire file's XML structure. A single malformed tag, a missing closing bracket, an unescaped ampersand in a connection string, a duplicate key in <appSettings>, will cause a ConfigurationErrorsException at startup and a 500 error on every request. Run the file through an XML validator or use Visual Studio's built-in XML editor, which highlights syntax errors inline.
Advanced Troubleshooting for ASP.NET Web Apps Errors
Disabling FCNMode When File Change Notifications Are Causing Too Many Recycles
If you've excluded your application folders from antivirus scanning and you're still seeing constant AppDomain recycles, the nuclear option is to disable File Change Notification mode entirely. This tells ASP.NET to stop monitoring the file system for changes, which means it won't automatically pick up updated DLLs or config changes without a manual recycle, but it also stops the spurious recycling entirely.
You can set FCNMode in your web.config or machine.config using the httpRuntime element:
<httpRuntime fcnMode="Disabled" />
Microsoft explicitly does not recommend disabling FCNMode for most scenarios, it's a trade-off that makes your deployment workflow more manual. On shared hosting or environments where you have no control over antivirus software, it may be your only option. Use it carefully and document it in your runbook, because your team will wonder why config changes don't take effect automatically.
An intermediate option is fcnMode="Single", which reduces the number of file system handles ASP.NET holds open by monitoring the root directory with a single watcher instead of individual watchers per directory. This reduces the surface area for false triggers while keeping automatic change detection alive.
Using Process Monitor to Trace Unexpected File System Events
When you can't tell what's triggering AppDomain recycling, download Process Monitor (part of the Sysinternals Suite) and run it on the server during the problem window. Filter by path to your application root and look for processes other than w3wp.exe writing to or reading from your monitored directories. Antivirus processes, backup agents (vssvc.exe, wbengine.exe), and even Windows Search indexing (SearchIndexer.exe) show up clearly here.
Checking the ASP.NET and IIS Configuration Hierarchy
Remember that web.config inheritance goes from machine.config down through parent application configs to your application's own config. A change to machine.config, made by a Windows Update, a .NET Framework patch, or an administrator, unloads every AppDomain on the machine simultaneously. If you see mass recycling across all your application pools at the same time, check whether a system update ran that evening.
Use this PowerShell snippet to compare the current machine.config against your last known-good backup:
Compare-Object `
(Get-Content "C:\Backup\machine.config") `
(Get-Content "$env:windir\Microsoft.NET\Framework64\v4.0.30319\Config\machine.config")
Diagnosing 503 Errors Specifically
An HTTP 503 from an ASP.NET application almost always means the application pool is stopped, the worker process crashed, or the request queue is full. In IIS Manager, go to Application Pools and look for pools with a Stopped status. Check the Windows Application Event Log for the corresponding error, look for Event ID 5002 (worker process failure) or Event ID 5021 (app pool disabled after rapid fail protection triggered).
Rapid fail protection is IIS's built-in circuit breaker, it stops an application pool after a configurable number of worker process failures in a short window. By default, this is 5 failures in 5 minutes. To see the current settings, in IIS Manager, click your application pool, then Advanced Settings → Rapid Fail Protection. During active debugging, you may want to temporarily increase the failure threshold or disable rapid fail protection to prevent the pool from getting stuck in a stopped state while you're diagnosing the root crash.
APPCMD list config /config.commit:webroot). That data will get you past tier-1 triage immediately.
Prevention & Best Practices for ASP.NET Web Apps Errors
Most ASP.NET Web Apps errors are preventable. The teams I've seen run ASP.NET applications reliably for years share a few habits that catch problems before they reach production users.
First, treat your web.config like source code. It should live in version control, go through code review, and be deployed through your CI/CD pipeline, not edited manually on the production server. Direct production edits to web.config are one of the top causes of accidental AppDomain recycling and configuration drift between environments. Every time you save web.config on a running server, ASP.NET detects the file change and recycles the AppDomain. In a high-traffic moment, that's a 503.
Second, always run APPCMD backup before any maintenance window. One command, run before you touch anything, gives you a full-fidelity restore point for every IIS and ASP.NET configuration file on the machine. Build it into your deployment runbook as a mandatory first step, not optional.
Third, set up antivirus exclusions as part of your server provisioning process, not as a reactive fix after you hit problems. If you're using infrastructure-as-code (Ansible, Terraform, PowerShell DSC), encode the exclusions in your server configuration scripts so every new server is configured correctly from day one.
Fourth, monitor AppDomain recycle events proactively. Set up a Windows Event Log alert for Event ID 1325 (AppDomain unload) through your monitoring platform, whether that's Azure Monitor, PRTG, Datadog, or a simple PowerShell task. When you get an alert, you can investigate the cause while the server is still running normally, rather than after users are already hitting errors.
- Add all ASP.NET application directories and the Temporary ASP.NET Files folder to your antivirus exclusion list on every server before the application goes live
- Run
APPCMD add backupas the very first step in every deployment runbook, before any files are changed - Enable IIS Application Initialization with
AlwaysRunningmode on application pools that serve latency-sensitive requests - Set up an alert on Event ID 1325 in your monitoring platform so unexpected AppDomain unloads surface as incidents, not user complaints
Frequently Asked Questions About ASP.NET Web Apps Errors
Why does my ASP.NET app restart randomly with no code changes?
This is almost always caused by file system events in directories that ASP.NET monitors using ReadDirectoryChangesW. The most common trigger is antivirus software scanning the application's bin, App_Code, or Temporary ASP.NET Files folders and touching files in a way that registers as a write event. Backup software, search indexers (Windows Search), and even some network drives can do the same thing. Start by checking the Windows Application Event Log for Event ID 1325, the reason field will tell you which file or directory triggered the recycle. Then add antivirus exclusions for the affected paths as described in Steps 1 and 3 of this guide.
Should I disable FCNMode to stop AppDomain recycling?
Disabling FCNMode stops all file-change-triggered recycling, but it also means your application won't automatically detect legitimate changes, like updated DLLs after a deployment. You'd need to manually recycle the application pool after every deployment. Microsoft does not recommend disabling FCNMode as a first-line fix. Try antivirus exclusions and the fcnMode="Single" setting first, those preserve automatic change detection while reducing false triggers. If neither works and you're in a controlled environment where deployments are always manual recycles anyway, then fcnMode="Disabled" is an acceptable trade-off, but document it clearly so your team knows why config changes don't auto-apply.
How do I back up my web.config before making changes in IIS?
The cleanest method is the built-in APPCMD tool. From an elevated command prompt, run %systemroot%\system32\inetsrv\APPCMD add backup YourBackupName. This backs up the entire IIS configuration including applicationHost.config and all associated web.config files in a single step. To restore it, run APPCMD restore backup YourBackupName. For individual web.config files, use the IIS Configuration Editor in IIS Manager to locate all config file paths, then copy each one manually to a backup directory. Give each backup a date-stamped filename like web.config.2026-04-20 so you can identify the right version quickly under pressure.
What causes a 503 Service Unavailable in ASP.NET applications?
A 503 from an IIS-hosted ASP.NET application almost always means the application pool is stopped or the worker process crashed. Open IIS Manager, go to Application Pools, and look for any pool with a Stopped status, click Start to bring it back up temporarily. Then check the Windows Application Event Log for Event IDs 5002 (worker process crash) or 5021 (pool stopped by rapid fail protection after too many crashes). The 5002 event will usually include the exception or error code that caused the crash. Common causes include stack overflows from infinite recursion, out-of-memory conditions, or unhandled exceptions in application startup code. Fix the underlying crash first, just restarting the pool is a band-aid that won't hold.
Why is my ASP.NET app so slow on the first request each day?
That's a classic cold-start symptom. By default, IIS shuts down the worker process after 20 minutes of idle time. The next morning's first request wakes the process up, which triggers a full AppDomain initialization including JIT compilation of your application's code, and that can take 10 to 60 seconds on a complex app. Fix this by setting the application pool's Idle Time-out to 0 in IIS Manager (Application Pools → your pool → Advanced Settings → Process Model → Idle Time-out), and enable IIS Application Initialization with doAppInitAfterRestart="true" and a lightweight initialization page so the app warms up before user traffic hits it. You'll see response times normalize to milliseconds on the first request.
Is it safe to leave the ASP.NET web service documentation protocol enabled in production?
No, and not just for performance reasons. When the documentation protocol is enabled, any browser request to your ASMX service endpoint generates a full HTML page listing every operation, every parameter name, and every data type your service accepts. This information is useful to a developer and equally useful to an attacker probing your service. It can also trigger WAF rules that block the endpoint and cause 403 or 503 errors for legitimate SOAP clients. Disable it by adding <remove name="Documentation" /> inside a <protocols> block under <webServices> in your web.config. This has zero impact on real SOAP and REST clients, it only removes the browser-facing documentation layer.