Home About Lessons Blog On The Mic Contact Projects
Lessons DEPLOY · C#

Cold Start Problem on Shared Hosting and Warmup Cron

8 min read · Emre Ulutabak
1
What is cold start?

One morning you open your site, and the page stays blank for 8-10 seconds. You panic — "did the server crash?" But the page loads, everything works fine. The next clicks open instantly.

This is cold start. When your application hasn't received a request for a while, IIS unloads it from memory and shuts it down. When the next request arrives, the .NET runtime has to boot from scratch, set up the DbContext, fill the DI container with services — that's where the few seconds of delay comes from.

It's not a big deal for a user-facing page, but it's a serious problem for a license validation API. A customer's plugin asks the API on every startup — if the API is asleep, the plugin looks frozen.

Not: aşağıdaki dakika değerleri örnek amaçlıdır — gerçek süre hosting sağlayıcısına ve panel ayarına göre değişir.

Note: the minute values below are illustrative — the actual duration depends on your hosting provider and panel settings.

💡
Cold start isn't a bug — it's a resource-saving behavior IIS does by design. On shared hosting, hundreds of sites share the same server — idle applications are shut down so they don't hog RAM.
2
Why does the application "sleep"?

The culprit is IIS's App Pool Idle Time-out setting. This duration isn't fixed — it depends on the hosting provider and panel configuration; some panels set it as short as 5 minutes, others 20 minutes or more. If an application receives no requests during this window, IIS shuts down the worker process (w3wp.exe). It reclaims the memory so other sites can use it.

On a dedicated server you could change this from IIS Manager, or even switch to "Always On" mode. But on shared hosting this option doesn't exist — your access to Application Pool settings is restricted, because the hosting company manages that pool, not you.

It's worth finding out the actual value on your own panel first (ask your hosting provider, or check the panel documentation). But in practice the question becomes: if you can't change IIS, how do you keep your application "busy" so it never sleeps?

3
The warmup cron solution

The solution is based on a simple idea: before the idle timeout runs out, send your application a request yourself, from outside. Since the application is never idle, IIS never gets the chance to shut it down.

For this, you first need to add a lightweight "ping" endpoint to your application that requires no authentication:

csharp
[ApiController]
[Route("api/[controller]")]
public class PingController : ControllerBase
{
    // AllowAnonymous — cron job giriş yapmıyor, sadece uyandırıyor
    [HttpGet]
    [AllowAnonymous]
    public IActionResult Get()
    {
        // Ağır bir iş yapma — tek amacı process'i canlı tutmak
        return Ok(new { status = "awake", time = DateTime.UtcNow });
    }
}
💡
Don't connect the ping endpoint to the DB. Its only purpose is to keep the IIS worker process alive — if you add a DB query, you add unnecessary load, and the cron itself starts failing whenever the DB is down.
4
Setting up cron in Plesk

Once the endpoint is ready, next you need a scheduler to call it at regular intervals. In Plesk this is under Scheduled Tasks.

To trigger well before your idle timeout runs out, a task running every 3 minutes usually leaves a safe margin — but if you don't know your panel's actual timeout, it's worth finding that out first:

powershell
# Plesk Scheduled Task — cron ifadesi
# Her 3 dakikada bir, saatin her dakikasında (0, 3, 6, 9 ... 57)
0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * *

# Çalıştırılacak komut (curl ile)
curl -s -o /dev/null -w "%{http_code}" https://api.emreulutabak.com/api/ping
💡
There's no need to write "every minute" (* * * * *). A 3-minute interval leaves a safe margin on most panels — but if you know your own panel's idle timeout, set the cron interval accordingly (keeping it noticeably shorter).
5
Verification and monitoring

After setup, you need to confirm the solution is actually working. A few methods:

  • Plesk Task Log — shows the output of each run, check here whether it returns HTTP 200.
  • Manual test — don't send any requests to the app for a bit longer than your known idle timeout, then open a page. If the cron is working, there should be no delay.
  • stdout log — if needed, enable it temporarily and confirm from the log that a request really does arrive every 3 minutes.
6
Golden rules
  • ✅ The ping endpoint must be [AllowAnonymous] — the cron shouldn't need to log in
  • ✅ The ping endpoint should not touch the DB — it only keeps the process alive
  • ✅ The cron interval should be noticeably shorter than the idle timeout (e.g. if your panel's timeout is 5 min, trigger every 2-3 min)
  • ✅ If you have multiple subdomains/applications, set up a separate ping + cron for each
  • ✅ Check the task log regularly — it can fail silently
7
Mini quiz
MINI QUIZ
The IIS App Pool Idle Time-out duration varies by hosting provider (some panels set it as short as 5 minutes). If you can't change this setting, what's the most practical way to stop your application from sleeping?
Calling an anonymous ping endpoint via cron at intervals shorter than 20 minutes
Putting the application into a background loop that constantly queries the DB
Setting hostingModel to inprocess in web.config
Waiting for the hosting company to manually change the Application Pool settings