On Windows shared hosting and Windows Server IIS boxes, the app pool is the process boundary that decides whether an ASP.NET site feels solid or randomly flaky. Most “it worked until 3 a.m.” tickets are not mysterious framework bugs — they are default recycle intervals, aggressive idle timeouts, or a 32-bit worker process that exhausted virtual address space while the machine still had free RAM.

If you run ASP.NET Framework or ASP.NET Core in-process on IIS 10.0, thirty minutes on app pool settings usually buys more stability than another profiling pass. Below is the hosting-floor checklist that keeps recycles predictable instead of surprising.

#Recycling is required — make the clock yours

IIS recycles application pools to reclaim memory and recover from leaks. Default regular-time intervals (often every 29 hours from first start) drift relative to your traffic pattern. Overlapping recycle should stay on so the new w3wp starts before the old one drains. Disable or raise idle timeout for sites that must stay warm; cold starts on shared hosts punish the first visitor after a quiet stretch.

Prefer a single scheduled recycle in the lowest-traffic window over “whenever memory looks high.” Guessed private-memory caps cause thrash: the pool hits the ceiling, recycles, warms up, hits the ceiling again. Measure steady-state private bytes under real load first, then set a ceiling with headroom — or leave memory limits off and fix the leak.

xml
<recycling>
  <periodicRestart time="00:00:00" memory="0" privateMemory="0">
    <schedule>
      <add value="04:15:00" />
    </schedule>
  </periodicRestart>
</recycling>
<!-- idleTimeout: set high or zero for always-on sites;
     overlapping recycle remains enabled by default -->
  • One scheduled recycle in off-peak local time beats a rolling 29-hour timer.
  • Set private memory limits only after you know working set; otherwise you manufacture outages.
  • Idle timeout of 20 minutes is a shared-host default, not a production requirement for sticky warm sites.
  • Overlapping recycle keeps requests flowing; turn it off only if you truly need single-instance in-process state.

#32-bit vs 64-bit and Full Trust

Many Windows shared plans still default pools to 32-bit for old native modules. A 32-bit w3wp tops out near 2 GB of user-mode address space even on a fat host. Large Object Heap pressure, big in-memory caches, or heavy EF materialization will recycle or crash the pool long before Task Manager shows the server “out of memory.”

If your stack is managed .NET Framework 4.8.1 or .NET 10 and you do not load 32-bit-only COM or ISAPI filters, run the pool as 64-bit. Full Trust on shared Windows hosting removes legacy CAS friction so apps can use the same APIs you use on a VPS — but Full Trust does not lift the bitness ceiling. Bitness is a process flag on the app pool, not a trust level in Web.config.

Quick check: if private bytes climb past ~1.2–1.5 GB on a 32-bit pool and recycles cluster around that line, flip to 64-bit before you rewrite caching. Confirm with your host that no required module is 32-bit-only, then recycle once and watch the working set under the same load.

#What a recycle destroys — and what Web.config should own

A recycle tears down the AppDomain (classic ASP.NET) or the in-process ASP.NET Core host. In-memory cache, static singletons, and in-process background work vanish. If you cannot afford sticky single-instance state, keep session and queues in SQL Server or another external store. Connection strings and environment-specific settings belong in config you can transform at deploy time — not hard-coded and not edited live on production after every publish.

xml
<connectionStrings>
  <add name="AppDb"
       connectionString="Data Source=SQLHOST;Initial Catalog=AppDb;Integrated Security=False;User ID=app_user;Password=***;Encrypt=True;TrustServerCertificate=False"
       providerName="Microsoft.Data.SqlClient" />
</connectionStrings>
<!-- Use publish transforms or host env overrides for
     staging vs production; never commit production secrets -->

For ASP.NET Framework sites, Web.config transforms (publish profiles or SlowCheetah-style) remain the practical standard on IIS. For ASP.NET Core, prefer environment-specific appsettings and host-level environment variables when the site runs out-of-process; in-process still honors the same configuration stack but shares the worker lifetime with the pool. Either way, a recycle should never require a manual connection-string edit on the server.

#Logging and capacity signals that matter

When the pool recycles, Windows can write to the Application event log (look for WAS and IIS-W3SVC-WP sources). Your app should log startup and orderly shutdown so you can correlate “users saw blips” with “worker replaced at 04:15.” On shared hosts, failed-request tracing is useful in short bursts and expensive if left on — disk quotas are real. For ASP.NET Core in-process, point stdout logs at a folder you can pull from the control panel, then turn verbose logging back down.

Capacity planning on a single IIS worker is blunt but honest: watch private bytes, request queue length, and recycle frequency. If you constantly ride a memory ceiling, you need less in-process cache, a leaner working set, or a larger plan — not a tighter recycle timer. If CPU spikes only on first request after idle, fix idle timeout and pre-load rather than scaling out prematurely. Shared Windows hosting is not Kubernetes; one well-tuned pool still carries a surprising amount of real traffic when bitness, recycle schedule, and externalized state are right.

Practical takeaway: put one off-peak scheduled recycle on the calendar, run 64-bit unless you have a documented 32-bit dependency, raise or disable idle timeout for warm sites, keep overlapping recycle on, and move anything you cannot lose out of process memory into SQL Server or durable config. On Windows hosts that expose Full Trust, Web Deploy, and real IIS app-pool controls, those knobs are usually one control-panel screen or support ticket away — use them before you chase ghosts in application code.