High traffic WordPress hosting
Although I have a rather large amount of servers at my disposal, for some time I’ve had my personal website hosted with 5quidhost on one of their Turbo pans. They’re an UK-based company with headquarters in Scotland, and have recently celebrated their 10th anniversary. They also rank quite high on TrustPilot, usually 1st or 2nd place.
In March I snapped up a domain that I had been waiting for a long time to become available: myatu.com. In fact, it is the reason why the current domain name has an “s” in it. I was aware of the content the previous owner had hosted on that domain name, but I had no idea how popular it was. So when that domain was transferred into my ownership, its traffic followed.
Generally, my website generates just a few thousand page views per day with the occasional spike, mainly for the Proxmox how-to guides (which I really should update one of these days!). Though around the end of March, this jumped to 24,000 page+ page views per day. Between March 27 and April 5th, more than 157,000 page views were generated, and is currently handling between 250,000 and 450,000 page views per week.
So, how did the website cope with this? Perfectly fine! It isn’t the first time the website has been hit with a large amount of page views, so I had already prepared the website for this. And the magic ingredient for that is: cache.
Install, but don’t forget
Because WordPress is pretty much a click-and-install solution, especially at 5quidhost, I have a feeling that many assume that this is the extent of what they need to do. Despite being riddled by uncommented spaghetti code, by default WordPress is fairly efficient. But as people start using it, they’ll also add themes to personalise it and plugins to perform certain tasks. More spaghetti! In the end, too much pasta has been fed to the website and now have a sluggish beast to tame.
The first step to take here, is to ask yourself if you really need all the plugins that you have installed. Each active plugin is loaded during each WordPress page visit, and these are loaded consecutively meaning they all have to wait for their turn. Some plugins are smart enough to stop loading themselves any further beyond minimal requirements, but I have seen plugins that seem to load the entire contents of the British Library for no apparent reason.
To help weed out the slow plugins, you can use a plugin profiler. My personal favourite is P3 (Plugin Performance Profiler), which has a simple interface giving a quick overview over how much time each plugin is spending during a page visit.
Also, WordPress.org has a very large plugin repository, and it serves to read the reviews of the plugin you have installed or intend to install. You may want to keep an eye on the last time it has been updated as well, as older plugins tend to develop issues as WordPress and PHP is updated. Above all, spend some time looking at the less popular alternatives — very often a plugin developer creates a competitor to a popular plugin that does a much better job.
Themes are slightly different than plugins, but can still be a major cause for things to slow down. There are a number of themes out there that use “LESS” (or similar) to compile custom CSS stylesheets. This works well enough for a theme that does this once only, and then stores the result on disk until another change is made.
However, I have seen quite a large number of themes that re-generate the CSS on each request. The CSS request invokes WordPress, which in turn loads plugins, before it can finally get to generating the CSS. I’ve seen it take 3 seconds or more for these type of requests, which adds to the (already slow) load time of the page. And as most browsers won’t display the page until it has obtained the CSS stylesheet it needs to render that page, this means the visitor is just waiting for something to happen on their screen.
It is fairly easy to see the above using a debugging console available for most browsers, such as the built in Developer Tools in Google Chrome (press F12, click the “Network” tab and reload the page), or Firebug. An online tool to diagnose this can be found at Pingdom, using the “Pingdom Website Speed Test” — when using that tool, you may wish to click the “Settings” underneath the field where you enter the domain of the site, and select the nearest location of the hosting provider to have a more accurate view of response times.
(W3 Total) Cache
Once you have sorted through your plugins and theme to find and resolve any issues they may have, the next step is to implement a cache. WordPress does very little caching of its own, so for this you will need to use a plugin. The one that I use and highly recommend is W3 Total Cache, though I would recommend not to use its “Minify” option as I have found that it causes more trouble than solve them — For minify I’m using an alternative solution, which I’ll discuss later.
The “Page Cache” option caches the output of each WordPress page. It will serve this output on subsequent requests, so that WordPress (and its plugins / theme) does not need to go through all the motions again to generate the output. When a page has changed, such as when you update a post, the cache for that page is purged. You can also manually purge the cache, either for an individual post or all of it.
I have this enabled on this website, using the Basic disk storage option. The enhanced option bypasses WordPress entirely by a clever use of the .htaccess file, but at the same time can actually bypass a bit too much for my taste. The other options are not available at 5quidhost, as they do not have Memcache or use a PHP opcode cache. While those caches are in held in much faster RAM, it would also open a huge can of worms with regards to security on a shared hosting provider (and if a shared hosting provider has this enabled, I would seriously question why).
Additionally, I have also enabled the “Cache Preload” option for the Page Cache, updating 10 pages at a time. If this is disabled, a page is cached only when someone visits it. For the SEO conscious, they know that page load times may count towards the ranking of a page, so if a page hasn’t been visited until a crawler bot reaches it, then the page load time can be slow. Using this option, the cache is primed before anyone has actually visited it.
The only drawback of priming the cache, is that they generate many small files. While it isn’t so much an issue in general, a problem arises whenever you want to upgrade WordPress or any of its plugins / themes, as W3 Total Cache will empty the entire cache (so as not to cause any issues with the upgrade). Deleting the thousands of small cache files can take some time, to the point the browser may time out, giving the impression the website has crashed. It has not, however, so just retry loading again.
An option in W3 Total Cache that complements the “Page Cache” is the “Browser Cache”. By default, WordPress / PHP sets an HTTP header that causes the browser to always fetch a page from the server, even if the contents can be cached. This is because the output of PHP is considered dynamic (always changing), whereas HTML pages are static of nature (hardly ever changes).
The “Browser Cache” option ensures that behaviour is changed more akin to static HTML pages, in which the visitor’s browser will try and load the page from its own cache first. Of course, the browser will still do some checks, such as checking how long it has been cached or if the page has been changed in meantime on the web server by making a very small, efficient request rather than a full page request.
Something that may not be immediately obvious, is that the cache times listed in the “Browser Cache” is the time the “Page Cache” will remain valid for, before W3 Total Cache considers it stale (at which point it will purge or generate a new cache for the page).
Object and Database Cache
However, it is possible that a call to the MySQL database by the AJAX code results in the same result coming back from the database server , such as for example a configuration, which can be cached by W3 Total Cache. Even when cached to disk, this can be faster than querying the database server itself, especially if it is heavily loaded with other requests or the request itself is very complex (read: inefficient).
With the above, WordPress should already be much snappier. However, as is the case with 5quidhost, shared hosting platforms usually limit the number of scripts that can run at the same time per website or hosting account. This is because a single script can take up a considerable amount of CPU and RAM, and when tallied up for all the websites on the server, this can add up to quite a significant number and affect the performance of the server.
The Turbo accounts at 5quidhost provide quite a bit more resources than their standard hosting accounts, and so have upped the number of scripts that can run at the same time as well. Though for 20,000+ page views per day, this may still not be enough, especially if these pages have not been cached locally (see the “Browser Cache” mentioned earlier) and there are many concurrent visitors at a time.
Enter CloudFlare. In their own words: “CloudFlare is a free global CDN and DNS provider that can speed up and protect any site online” — Well, their basic plan is free, however that plan is more than sufficient for many. Not only does CloudFlare help protect your website against unwanted traffic, such as the unscrupulous spammers for example, but they also provide a CDN, which is what will help a high traffic website tremendously.
CDN stands for “Content Delivery Network”. Essentially, it is a large number of servers spread across the world that serve content on behalf of your own website. The way it works with CloudFlare is that they sit in between your web site and the visitor. Instead of the visitor directly querying your website for content, it actually asks CloudFlare. In turn, CloudFlare will check if it has the content requested, and if not, asks your website’s server for it. It then delivers this back to the visitor.
If you have setup W3 Total Cache in WordPress to cache pages like I have, then this means CloudFlare can also cache them on their own servers. The net result is that the bulk of the requests are actually handled by CloudFlare, not by the server at 5quidhost. And because CloudFlare has many, many servers across the world handling each page view as opposed to just a single server, it can easily take a hit for 20, 30 or even 100,000 page views per day.
5quidhost actually offers very easy integration with CloudFlare directly from their control panel, which is described in one of their blog posts. However, it only accounts for a domain with a prefix such as “www.myatus.com" or “blog.myatus.com”, not one without as is the case with my website (“myatus.com”). In such instances, you would need to sign up directly with CloudFlare and use CloudFlare’s DNS servers. Though the entire process of doing it that can be done within 15 minutes, and is well worth the time.
The end result is that my website has increased its speed significantly, where a page can load in under a second, whilst it can handle in excess of 20,000–100,000 page views per day.