At HostNexus we use native Nginx caching via the proxy_cache directive. We combine this with Redis caching to deliver websites that load at fantastic speeds.
WordPress is a fantastic platform that revolutionized the way we manage and publish content. Ten years ago it was fast right out of the box. You’d add a simple theme, install a few plugins and it would be almost as fast as a static HTML site. But times have changed and WordPress is no longer a simple blog. It’s a full content management system with almost limitless possibilities. These days your typical active WordPress site has a theme with complex options and 20 to 30 plugins enhancing its functionality. It will suck server resources and will be generally slow to load. There a lot of things you can do to optimize your WordPress site’s performance but right up there at the top of your list should be caching. At HostNexus we have you covered with our native Nginx caching.
What is Nginx Caching?
WordPress uses PHP to build every one of your pages and render it to a browser in HTML. By using a cache solution you can store the output of all those PHP requests (your static assets and HTML) on the server. When another visitor accesses the page, they are served stored (cached) HTML assets instead of compiling PHP and making multiple database requests. The end result is a faster loading page and helps reduce overall load on your server.
Everyone should be familiar with a browser cache. When you access a site for the second time it loads in an eye blink. This is because the site’s assets like images are already stored on your computer. The browser is loading those images from your computer rather than the server. Server side caching works in a similar way. Your pages are stored as a hashed key in the server’s memory. So when a visitor loads your page the server checks for the key and serves assets from the cache rather than compiling PHP and querying the server.
But what about my favorite Page Cache plugin?
If you want to use your favorite cache plugin that is also fine. Just delete the Redis Page Cache plugin if we installed it on your WordPress instance at account set up.
Let’s go through the caching layers from top to bottom. In the application and CDN layer you should pick and choose the best solution for you. There are benchmark and use cases to make your decision easier.
Browser Cache
Everyone should be familiar with this. When a visitor loads a website their browser sends a request (request header) to the server and the server responds (response header). The response header tells the browser important information like whether assets on the loaded page can be cached. I’m sure many people have added rules to a .htaccess file to control their caching. A properly configured server should have this already configured. At HN you don’t have to worry about leverage browser cache .htaccess rules. Also don’t worry about GZIP (Vary: Accept-Encoding), it’s default, as is Keep-Alive and HTTP/2.
Bytecode Cache
A bytecode cache has been shipped with PHP since version 5.5. Experienced users might remember its previous incarnation as the Zend Optimizer. While it was a free addon to PHP it was closed source. It was then re-branded to OpCache and is now distributed with PHP core. Understanding what OpCache does requires some knowledge of how PHP works. When a PHP script is processed it is parsed and compiled into code called opcode that the server can read. OpCache stores this machine-readable opcode in server memory. If the same PHP code is requested the machine-readable data is quickly retrieved, skipping the parsing and compilation phase, thus increasing the performance of an application like WordPress.
Redis Object Cache
Redis is an open-source key value store that can operate as both an in-memory store and as cache. When a visitor loads a WordPress page, multiple database queries are performed on the server to render the content. Redis stores (caches) these queries and the result. So, when another visitor loads the WordPress page, the results are provided from Redis and from memory. The database isn’t queried increasing performance and saving valuable server resources.
Please do not confuse the Object Cache with the Redis Page Cache mentioned next. While they both use Redis their use cases are very different and they cannot be used simultaneously. The Redis Object Cache will not store a WordPress’s generated HTML. The Redis Object Caches stores MySQL queries and their output in Redis. So, to clarify:
- Redis Page Cache – caches the HTML output of PHP compilation and database queries.
- Redis Object Cache – caches the MySQL queries used to render WordPress pages.
For a standard WordPress website or blog where content changes infrequently Redis Page Cache will be easier to manage and faster. Infrequently here can mean a few new posts a day and low comment traffic. Highly dynamic WordPress websites with many new posts per day, active comment threads and membership areas could benefit from Redis Object Cache. Ecommerce sites running WooCommerce and discussion forums like BuddyPress are also good candidates – although they are notoriously difficult to configure optimally.
Redis Page Cache
This is a simple and lightweight WordPress plugin. Just install and activate with no configuration necessary. It’s a Page Cache mechanism just like W3TC but it uses Redis and stores the page cache in-memory. The ability to store the cache in-memory is what makes it faster than all the other page cache plugins. With the added bonus of not risking throwing your monitor out the window due to 20 pages of configuration and troubleshooting. It purges the cache when you edit or publish content and y0u can also manually purge the cache from the admin toolbar.
There are situations where Nginx might not cache certain pages so this is a good backup and the two will work well together.
The Redis Page Cache plugin adds a Response Header call x-pj-cache-status:
Improve Redis Cachability
Redis may deliver cache misses on some pages that set cookies. You can improve overall cachability by telling Redis to strip the cookies from requests. First, create a redis-page-cache-config.php and place it in the root of your WordPress install. Place the following code in wp-config.php to include this file during runtime:
// After the ABSPATH definition, but prior to loading wp-settings.php
require_once( ABSPATH . 'redis-page-cache-config.php' );
In this redis-page-cache-config.php list your cookies like this:
$redis_page_cache_config = array();
// Ignore/strip these cookies from any request to increase cachability.
$redis_page_cache_config['ignore_cookies'] = array( 'cookie_1', 'cookie_2' );
You can also control how often Redis will auto-purge its cache:
// Change the cache time-to-live to 1 hour
$redis_page_cache_config['ttl'] = 3600;
IMPORTANT! Remember to start your redis-page-cache-config.php file with <?php.
Nginx Caching
This should be the meat-and-potatoes of your caching solution. All domains are created with Nginx Caching enabled. In our Plesk WordPress Toolkit you can activate and deactivate nginx caching.
These are our standard Nginx Caching rules that are accessed by clicking Setup in the Toolkit or going to Apache & nginx Settings in Plesk:
Cache size and timeout can be increased as needed. As a general rule we only recommend serving the stale cached records if you have a highly dynamic site and you have a very short cache timeout (under 5 minutes).
As a general rule Nginx will not cache pages that set a cookie. If your site uses cookie and you are confident these pages can be cached you can add the names of the cookies in the “cache requests with cookies” field. To check if your site sets cookies can you use a website like this one.
Load your website in your browser and inspect your Response Headers in Developer Tools > Network. On first load you should see x-cache-status: MISS. And on reload it should return x-cache-status: HIT. Remember to test your website in your browser’s private mode (called Incognito Mode in Chrome for example).
The above screenshot is from GTMetrix. Analyze a page and click on Waterfall and then your domain name to get the response headers.
CDN Cache
A CDN cache stores your site’s static assets (JavaScript, CSS, and images) on a Content Delivery Network. A CDN provider has dozens of data centers location around the world that will all store your assets. It delivers these files to a website visitor from the CDN’s geographically closest data center rather than your hosting server. This can have a dramatic impact on performance for website visitors that are geographically distant from your website’s server location. At HostNexus our service is integrated with Cloudflare which has 152 data center locations around the world. Wherever your visitors may be Cloudflare has a data center near them. Easily activate Cloudflare from inside your Plesk control panel.
Clicking into ServerShield by Cloudflare will take you to a Cloudflare signup/login page. If you don’t have a Cloudflare account you can quickly signup here. If you have an existing account you can login and set up your new domain.
Once logged in or signed up you then need to activate Cloudflare.
Once activated it will modify some DNS records and you will be able to manage some basic functions by clicking Manage Cloudflare.
These are the Cloudflare functions available within Plesk:
If you use Cloudflare you will also be able to login to the Cloudflare Dashboard. We recommend you tweak some settings in there to maximize your site’s performance. We have a detailed tutorial on how to set up Cloudflare correctly.
If you use Plesk’s Cloudflare integration the CDN will only work with the www prefix of your domain. If you use domain.com rather than www.domain.com and wish to use Cloudflare you should signup with them directly. You will need to switch your nameservers to Cloudflare nameservers. Our Cloudflare tutorial applies both scenarios.
Cloudflare Railgun™
As a Cloudflare Optimized Partner we are able to offer Cloudflare’s Railgun service for free on our full suite of hosting services (even Cloud VPS and Dedicated Servers). Railgun is optimization technology that speeds up the delivery on non-cacheable content. On average around 65% of content is cacheable and delivered from the cache in Cloudflare’s geographically closest data centers. The remaining 35% cannot be cached by Cloudflare and those requests are sent to the origin server for processing. This can be due to misconfiguration, exceptions such as cookies or due to highly dynamic or personalized content.
Railgun uses a collection of techniques to compress and accelerate previously uncacheable web pages. So even when the origin server must process a website’s pages Railgun delivers them quickly. Railgun opens an encrypted, tunneled connection between the server and the Cloudflare network. It can analyze a page for markup changes and delivers only these changes to speed up page load times. Railgun is listed under Speed in the Cloudflare dashboard. When you add a site it will detect if your server has Railgun support.
Benchmarks
For testing we will be using GTMetrix. 15 consecutive tests were ran and the average result recorded. In this test we are using the WordPress Twenty Seventeen theme populated with demo content from another theme. A lot of people like to use Pingdom Tools but Pingdom will not give you an accurate result. It will lead you into thinking your site is faster than it actually is! This is due to two different methods these services use to measure when a page has finished loading. Pingdom uses the onLoad method which means the test terminates when a browser fires the “windows.onload” function. The problem with this method is that some scripts will not have finished loading when the browser triggers this signal. GTMetrix uses a method called Fully Loaded Time. This method terminates the test after 2 seconds of network inactivity then analyzes all activity up to that point. It is therefore much more accurate.
The metrics we are looking at are the Fully Loaded Time and TTFB (Time To First Byte). The first sets of tests are tagged as LOCAL meaning the tests were done from a data center location close to where the website’s server is located (Dallas, TX). The second set of tests tagged as REMOTE are ran from a data center location in Sydney, Australia to analyze the effectiveness of the CDN.
Time to First Byte (TTFB) is the total amount of time spent to receive the first byte of the response from the server once it has been requested by a browser. It is a key metric and a main indicator of web performance. Optimizing application code, cache implemention, web server configuration, geographical location and server hardware can all impact TTFB.
Test #1 – Nginx Caching and Redis Caching (LOCAL)
On this set up Redis Page Cache and Redis Object give an almost identical result. This will not always be true – it depends on how your WordPress instance is set up.
- Load Time: 371ms
- TTFB: 64ms
Test #2 – Nginx Caching and Cloudflare CDN (LOCAL)
This set up use native Nginx Caching and Cloudflare’s CDN with normal caching rules. You can use Redis in this set up as well but there is such a thing as over-caching. Nginx + Redis does slightly outperform Nginx + Cloudflare CDN. You sacrifice a small hit to page load and TTFB in exchange for better results for your more remote visitors.
- Load Time: 452ms
- TTFB: 123ms
Test #3 – Cloudflare CDN Page Cache (LOCAL)
A little known Cloudflare feature is their ability to serve a Page Cache. This is a great option for non-dynamic WordPress sites and it’s really fast. Our Cloudflare tutorial shows you how to set it up. This will cache everything including the HTML output and overrides the host server’s Cache Control directives. It should therefore be used with the Cloudflare WordPress plugin so you can purge the cache every time you make a change on your site (new post, edit etc). Absolutely not suitable for dynamic websites with fast changing content. Also completely reliant on the speed of the Cloudflare network.
- Load Time: 500ms
- TTFB: 123ms
Test #4 – Nginx Caching and Redis Caching (REMOTE)
Without a CDN the test from Sydney is slowest with just Nginx and Redis. This is expected behavior if images are over 50% of your page.
- Load Time: 1600ms
- TTFB: 800ms
Test #5 – Nginx Caching and Cloudflare CDN (REMOTE)
With the Cloudflare CDN backing up Nginx Caching this test from Sydney is looking better.
- Load Time: 1000ms
- TTFB: 412ms
Test #6 – Cloudflare CDN Page Cache (REMOTE)
The Cloudflare Page Cache method is easily the fastest running test from Sydney.
- Load Time: 500ms
- TTFB: 190ms
Conclusion
The cache solution you decide to implement will depend on the location of the majority of your visitors. If the majority of your visitors are somewhat local (same country) you should use the standard Nginx caching with Redis Page/Object cache.
If you have a lot of international visitors with a site that is dynamic in nature the standard Nginx + Cloudflare set up will work well for you.
For a website that is somewhat static in nature with lots of international visitors the Cloudflare Page Cache method is an obvious choice.