This is an IIS built-in feature : in order to preserve resources IIS will cycle the application pool after a set time without requests, thereby making the next request painfully slow as the application pool have to startup.
Many masters of low-traffic websites, me included, do NOT like this behaviour, we don't want our server to do nothing being slow to serve that lone request we long so much for - therefore we need a way to avoid the application pool recycle.
It seems Microsoft have built a way to configure IIS to NOT recycle the application pool or to change the idle time threshold and many suggestions of how to configure IIS
Schedule an automated request - this works
We will use Task Scheduler to create an automated request every 1 minute thereby avoiding IIS from recycling the application pool - avoiding slow response from our ASP.NET Core website.
There are 4 main steps to setup this scheduled request :
- Filter the scheduled request out in any website statistics (here I will show how to do that for Google Analytics).
- Create a dedicated http endpoint for the scheduled request (not strictly necessary).
- Create the scheduled request.
- Test that the scheduled request is working by evaluate the IIS Log.
Ok, lets get startet :
- Filter the scheduled request out of Google Analytics
You don't want the scheduled request every minute in you Page View count.
- In Google Analytics Admin click on the "Filters" link for the website View there you want to filter the scheduled request out.
- In the "Filters" list click the "ADD FILTER" button.
- In the "Add Filter to View" page input the following :
- Method : "Create new Filter".
- Filter Name : a descriptive name, in my case "Topiqs Server".
- Filter Type : "Predefined".
- "traffic from the IP addresses"
- "that are equal to"
- IP Address : the IP of your webserver (where your scheduled request task is defined), in my case 22.214.171.124.
- Click the "Save" button to return to the Filters list.
- Your filter have been created.
- Create a dedicated http endpoint
(Note that a dedicated http endpoint is not strictly necessary but I find it more satisfactorily and it does have some potential advantages amongh others that you can activate any service on that endpoint that are not kept alive just by hitting the website)
- In your ASP.NET Core code editor, in my case Visual Studio, load any of your controllers, in my case I will use my AdminController, and add the following endpoint called KeepAlive :
public EmptyResult KeepAlive()
return new EmptyResult();
- Request your http endpoint in a browser to confirm it works, in my case it is https://topiqs.online/admin/keepalive and it should return an error free empty page.
- Create the scheduled request
- Open Task Scheduler on your web server. In the left pane select "Task Scheduler Library" and in the right plane click on "Create Task".
- In the "Create Task" dialog be sure the "General" tab is selected and
- Give the task a name : in my case the name is Topiqs KeepAlive.
- Select "Run whether user is logged on or not".
- Configure for whatever server you run on, in my case "windows Server 2012 R2".
- Select the "Triggers" tab and click the "New" button
- In the "Edit Trigger" sub-dialog
- Begin the task "On a schedule".
- Set the trigger to fire "Daily" every 1 day and start 12:00:01 AM (1 second after the day starts).
- Repeat task every "1 minute" for a duration of "Indefinitely". Note that you cannot select 1 minute (smallest is 5 minutes) but you can write it manually.
- Click the "OK" button to return to the "Create Task" dialog "Triggers" tab - you can see that a Trigger have been created..
- Select the "Actions" tab and click the "New" button
- In the "New Action" sub-dialog
- Set the Action to "Start a program".
- Program to start is powershell.
- Add arguments -ExecutionPolicy unrestricted -Command "(New-Object Net.WebClient).DownloadString(\"http://topiqs.online\")".
- Click the "OK" button to return to the "Create Task" dialog "Actions" tab - you can see an Action have been created. In the "Create Task" dialog "Actions" tab click on the "OK" button to finish creating the task.
- You are required to input the authentications details for the user under which the Task will run - this is because above in the "General" tab we specified that "Run whether user is logged on or not". Press the "OK" button.
- Back at the "Task Scheduler Library" we can see the new task have been created listed in the library.
- Test the scheduled request is actually happening
- In the "Task Scheduler Library" right click on the task just created, here "Topiqs KeepAlive" and select "Run" from the shortcut menu.
- Find your website log file (here I assume default IIS logging)
- Default IIS log files are located in %inetpub%\logs\LogFiles\, however each website have it's own sub-folder named W3SVC prefixed the website ID (this is true for the default IIS log format "W3C Extended").
- Open IIS management console and in the left pane expand sites and right click on the relevant website, here topiqs, and select "Manage Website | Advanced Properties"
- In "Advanced Properties" dialog box notice the website ID, in my case it is "6", which means the logging folder name is W3SVC6. Close the "Advanced Properties" dialog.
- Open the relevant log file in a text editor (there may be multiple log files for the same website in which case you just select the file postfixed the highest number)
- Scroll to the bottom of the file and find the KeepAlive request - the scheduled request task is working.
- The scheduled task requesting you website is now working at least once, however to test that the scheduling is actually workig wait 10 minutes and load your log file again.
- This time I evaluate the log file in Log Parser Studio (if you don't have Log Parser Studio, see IIS Logging) using the following SQL
- SELECT TOP 20 RowNumber, to_localtime(to_timestamp(date,time)) AS localtime, cs-uri-stem FROM 'C:\inetpub\logs\logfiles\w3svc6\u_ex200330.log' WHERE cs-uri-stem = '/admin/keepalive' ORDER BY RowNumber DESC
- Indeed the request is issued by the task scheduler every 1 minute!
Appendix : Often suggested solutions
Then I first started to look for a solution to the ASP.NET Core slow response, I came across several suggestions. None of these solutions worked for me, however since other people have said they worked, I will list them here for completeness.