Improving SharePoint First Time Page Loads with Warm-Up Scripts


I actually thought I had already written this blog post, but it turns out it never made it out of OneNote draft mode and into my blog.  It's about time I start writing again, so here's my first post in while, appropriately on warming up (SharePoint that is).

It's a fairly long post, so I here's a summary of what we're going to cover.

  • When SharePoint recycles every night, the first person in next experiences very slow page loads
  • Setting a scheduled task to "warm-up" SharePoint after this happens dramatically improves those first page loads
  • If you have client side code calling APIs (REST or CSOM), those APIs need to be warmed up too
  • You can configure IIS to have SharePoint recycle at a predictable time every night, and then warm up right after that

If you've ever been the first one to hit a site in SharePoint on premises, or gone back in after an IISReset recycle of your SharePoint servers, you know that the first page load can take a very long time.  This is because IIS (which SharePoint is running on top of) and ASP.NET Just-In-Time compiler creates native images of the ASP.NET code.

The reason you may experience this first thing each day is that the IIS App pools recycle every night.  The next person to access each site after this causes the JIT compilation and delay.  You can easily see what this looks like by simply doing an IISReset on the SharePoint WFE(s) and hitting the site with the browsers Developer Toolbar (press F12 in the browser) open on the Network tab.  I used our Envision Shakespeare Company dev reference site ( to test this, and got the results below.

What this shows is that the time to first byte (TTFB, which is a measure of how long it takes to process the page on the server) was 59.18 seconds.  I don't know about you, but that's an awfully long time to wait for a page.  And then the page rendered, but the rotator and rollups didn't show up for another 14 seconds after that (they are loaded client-side).

How does this compare to a normal page load?  That is shown below.  The TTFB was 1.93 seconds, and the rollups took another 1.18 seconds.  The dev server (or more specifically its SQL Server) is somewhat overloaded, but still a dramatically different time.

So how do we solve for this?  If you search for SharePoint warm-up scripts, you'll get lots of possible solutions.  The basic premise is to have something invoke a web request against each site on the farm.  I'm a fan of PowerShell, so I used a script from  It basically iterates through each web application on the server, and then iterates through each site collection within.  It executes a web request against each site collection, which "warms it up".

If you look at my first timings above, you'll see that not only did the page take 59 seconds to initially load, but then the rollups took another 14 seconds.  The reason for this is they are built with client-side code that calls the SharePoint REST APIs, which are another part of the site that needs to be warmed up.  To address this, we use the warmup-extrasites.txt file that is also supported.  Here we can list the REST end points we know we'll need, and get them warmed up too.  In our example this file has the following in it."True" OR contentclass:"STS_ListItem") %27&rowlimit=1

This is just one of the REST calls that get executed by the home page., but once we've warmed the one end point up, it's good to go for all of them.

The last thing to work out is when to run our scheduled task to do the warm-up.  If you dig into the depths of IIS, you'll see that the app pool settings for your site define one or more app pool recycle times.

While you could go through each app pool manually and set the recycle time, we can again leverage PowerShell to set this for all the app pools. It is actually fairly easy, and is a single line of PowerShell for each app pool.  For our test site, this consists of the following.

Import-Module WebAdministration

Set-ItemProperty -Path "IIS:\AppPools\SharePoint - shakespearedev.envisionit.com443" -Name Recycling.periodicRestart.schedule -Value @@{value="02:00"}

Once we've done this for each of our app pools, we can set a scheduled task to run our warm-up script just after this recycle time.

Latest Articles