Speed up WordPress on IIS 7.0

The performance of WordPress may be sufficient for an average blog that gets a few page hits per minute. However, if your blog post suddenly shows up on digg.com or any other social networking site, it may become challenging for server to handle such huge spike in traffic. A few options exist to help server to cope with flood of requests:

  • IIS Output Caching
  • WP Cache plugin for WordPress
  • WP Super Cache plugin for WordPress

In this post I will explain the benefits and drawbacks of each option and walk through the steps for configuring IIS and WordPress to use those options.

Prerequisites

Before performing the configuration steps described in this post, it is necessary to complete the following prerequisites:

  1. Install WordPress (Follow the instructions in this article or use the instructions from the official WordPress site).
  2. Install Microsoft URL Rewrite Module for IIS 7.0
  3. Enable “Pretty Permalinks” in WordPress by following steps described in this article.

IIS Output Caching

IIS 7.0 has a very powerful output caching infrastructure, which can cache response data in kernel-mode (http.sys) and in user-mode memory space (IIS worker process). The Output Caching can be used with static web resources as well as with semi-dynamic web applications, where the content is generated dynamically, but is not likely to change from request to request. A blog engine is a perfect example of semi-dynamic web application.

To enable IIS Output Caching for WordPress you can use IIS Manager UI:

EditCacheRule

Or add this configuration section into the web.config file located at the root folder of the WordPress site:

<caching>
  <profiles>
    <add extension="*" policy="CacheForTimePeriod"
             kernelCachePolicy="CacheForTimePeriod"
             duration="00:00:30" />
  </profiles>
</caching>

With this configuration IIS will cache the response generated by WordPress in memory for 30 seconds, thus avoiding heavy script processing and database I/O for all subsequent requests. This would increase the throughput significantly – for example on my Virtual PC the WordPress throughput grew from 10 requests per seconds to more than 2500 requests per seconds after enabling Output Caching.

However, there are certain drawbacks from using Output Caching. Some of the dynamic blog features are lost when cached page is served instead of a page generated by WordPress. For example, when a visitor submits a comment for a blog post there will be no confirmation message shown to indicate that the comment has been submitted. This is because the page shown to the user after comment submission is served from cache. This may cause visitor to submit same comment several times. This problem can be somewhat mitigated by reducing the cache timeout, but there is still a chance that stale page may be served to a visitor after comment submission. To reliable prevent this from happening a more customized solution for WordPress is necessary, which is a WP Super Cache plugin.

WP Cache and WP Super Cache

WP Super Cache is a very popular plugin that generates temporary static html pages from dynamic WordPress blog. After a html file is generated the server will serve that file instead of processing the comparatively heavier and more expensive WordPress PHP script. Since this is a WordPress-customized solution, it is able to smartly handle such situations such submission of comments or serving pages to logged on users. Specifically, the plug in will serve static html pages only to:

  1. Users who are not logged in
  2. Users who have not left a comment
  3. Or users who have not viewed a password protected post.

Typically 99% of the visitors do not do any of the above actions, so the static html pages will be served most of the time, thus increasing server throughput significantly.

WP Super Cache plugin has two modes of operation: WP-Cache and WP-SuperCache. With WP-Cache the static files are still generated but every request will require loading of PHP engine to serve those files. WP-SuperCache relies on URL rewriting to bypass PHP altogether when serving cached static files.

To configure WP Super Cache on IIS 7.0 follow these steps:

Step 0: Make sure that wp-content folder is writable by web server

Step 1: Download the WP Super Cache plugin and unpack it into the WordPress plugins folder “wp-content\plugins”. This will create “wp-content\plugins\wp-super-cache” folder.

Step 2: Copy the file “wp-content\plugins\wp-super-cache\wp-cache-config-sample.php” to “wp-content\wp-cache-config.php” and make sure WPCACHEHOME points at the right place.

Step 3: Copy the file “wp-content\plugins\wp-super-cache\wp-cache-phase1.php” to “wp-content\advanced-cache.php”

Step 4: Add the following rewrite rule to the web.config file located at the root folder of WordPress site. Make sure that the “WP Super Cache” rule is before the WordPress rule for pretty permalinks. Typically the <rewrite> section will look as below

<rewrite>
<rules>   <rule name="WP Super Cache" stopProcessing="true">     <match url="^(\d{4})/(\d{2})/(.+?)/?$" ignoreCase="false" />     <conditions>       <add input="{REQUEST_METHOD}" negate="true" pattern="POST" ignoreCase="false" />       <add input="{QUERY_STRING}" negate="true" pattern=".*=.*" ignoreCase="false" />       <add input="{QUERY_STRING}" negate="true"                 pattern=".*attachment_id=.*" ignoreCase="false" />       <add input="{HTTP_COOKIE}" negate="true"                pattern="^.*(comment_author_|wordpress|wp-postpass_).*$" ignoreCase="false" />       <add         input="{DOCUMENT_ROOT}\wp-content\cache\supercache\{HTTP_HOST}\{R:1}\{R:2}\{R:3}\index.html"         matchType="IsFile" />     </conditions>     <action type="Rewrite"          url="wp-content/cache/supercache/{HTTP_HOST}/{R:1}/{R:2}/{R:3}/index.html" />   </rule>   <rule name="Wordpress Pretty Permalinks" patternSyntax="Wildcard">     <match url="*" />     <conditions>       <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />       <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />     </conditions>     <action type="Rewrite" url="index.php" />   </rule>
</rules> </rewrite>

Note: this rule example is configured to work with WordPress permalinks that use “Month and name” format, e.g. http://wordpress/index.php/2008/12/sample-post/. If you use any other permalink format then the rule will need to be adjusted for that.

Step 5: Add the following line into the wp-config.php file above the “require_once(ABSPATH.’wp-settings.php’);” line:

define( 'WP_CACHE', true );

Step 6: Login to WordPress and activate the plugin by going to “Plugins” tab. Then go to “Settings” tab and click on “WP Super Cache”. If everything was configured correctly you should see the plugin’s configuration page.

WPSuperCache

Step 7: Go to “wp-content\cache” folder, which should have been created when plugin was activated. Create a new web.config file there, open it and paste the following content inside:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Cache-Control" value="max-age=300, must-revalidate" />
    </customHeaders>
  </httpProtocol>
</system.webServer>
</configuration>

This configures IIS to send Cache-Control response header for any of the cached html pages. That header will force the browser to expire the locally cached response after 5 seconds.

To check that the WP Super Cache actually works, set its status to ON in the plugin configuration page, then clear all the browser cookies and make a request to the blog page. Alternatively you can use WFetch to make a request. If WP Super Cache works then when you make a request to http://wordpress/2008/04/hello-world/, the response will be cached as a static file in \wp-content\cache\supercache\wordpress\2008\04\hello-world\index.html. When next time you request the same page, the rewrite rule “WP Super Cache” will rewrite the URL to the “wp-content\cache\supercache” folder, thus IIS will serve static html file without even invoking PHP engine.

Conclusion

Here is the comparison of server throughput in requests per second with three output caching solutions for WordPress when requesting http://wordpress/2008/04/hello-world:

PerfResults

The performance of WP Super Cache is comparable with performance of IIS Output Caching because with WP Super Cache IIS is just serving static files, which is what IIS is very good at.

So, when to use which option? Here are the pros and cons of each caching solution:

  Pros Cons
IIS Output Caching
  • Very easy to configure
  • Significantly improves site throughput
  • May prevent confirmation message from showing up when submitting comments
WP-Cache
  • Works without URL rewriting
  • Correctly handles comments submissions and other visitors’ actions
  • Not that significant performance gain comparing to other options
WP-SuperCache
  • Significantly improves site throughput
  • Correctly handles comments submissions and other visitors’ actions
  • More complex to setup and configure comparing to other options