Menu Search
Jump to the content X X
Smashing Conf San Francisco

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. upcoming SmashingConf San Francisco, dedicated to smart front-end techniques and design patterns.

A Look At The Modern WordPress Server Stack

Editor’s Note: Today marks a special day for WordPress. Powering many websites (and yes, Smashing Magazine is one of them), it celebrates its 13th birthday today. Happy birthday, dear WordPress! Here’s to many more!

Do you remember when you could run a “fast” WordPress website with just an Apache server and PHP? Yeah, those were the days! Things were a lot less complicated back then.

Now, everything has to load lightning-fast! Visitors don’t have the same expectations about loading times as they used to. A slow website can have serious implications for you or your client.

Consequently, the WordPress server stack has had to evolve over the years to keep up with this need for speed. As part of this evolution, a few gears have had to be added to its engine. Some of the older gears have had to change as well.

The result is that the WordPress server stack looks quite different today than it did a few years ago. To better understand it, we’re going to explore this new stack in detail. You’ll see how the various pieces fit together to make a WordPress website fast.

Overview Link

Before diving in, let’s zoom out and look at the big picture. What does this new WordPress server stack look like? Well, here’s the answer:

WordPress server stack diagram1

The diagram above gives a good overview of what the modern WordPress server stack looks like. At a high level, we can divide what’s going on into three areas:

  • the request-response cycle between the browser and WordPress;
  • WordPress (which is a script that the PHP runtime executes);
  • the query-result cycle between WordPress and the MySQL database.

The role of the modern WordPress server stack is to optimize these three areas. These optimizations are what make everything load faster. And the best part is that there are several ways to do it. (Yay!)

In most cases, these optimizations involve installing new services on your server. Sometimes, these services will need the help of a plugin to interact with WordPress. There will also be times when you can get away with just installing a plugin. You’ll see a lot of different options throughout this article.

The Request-Response Cycle Link

Everything starts with the browser. Let’s say you want to view the home page of modern.wordpress-stack.org. Your browser will start by sending an HTTP request2 to the web server that hosts it. At the other end, the web server will take your request and turn it into an HTTP response3.

This first response should always be the HTML content of the home page of modern.wordpress-stack.org (unless there’s an error). However, the job of your browser isn’t done. No, that home page still needs more files, the most common ones being CSS, JavaScript and images files.

So, the browser will send requests for those files. The web server will respond with the requested files (again, as long as there are no errors). This cycle will continue until the browser has enough information to render the home page. The faster this cycle happens, the faster the website will appear to load.

Now, this is an obvious simplification, but it’s how things work for the majority of WordPress websites.

Optimizing The Request-Response Cycle Link

All right, this brings us to the obvious question, How do we make a web server perform this cycle faster? This is a great question and is part of the reason why the modern WordPress server stack exists.

The stack exists because you can’t just make a web server faster. A web server is also a dispatcher. It can receive a request and just forward it to other services.

These other services are often the bottleneck of this request-response cycle. With WordPress, this bottleneck is PHP, which is why optimizing the request-response cycle comes down to two things. We want the web server to:

  • receive as few requests as possible,
  • forward as few requests to PHP as possible.

The modern WordPress server stack focuses on this last one. It wants to forward as few requests to PHP as possible. That’ll be the main goal for optimizing the stack.

We focus on the second goal because the stack can’t do much about the first one; it has no direct impact on it. The second one is addressed either by the web server’s configuration or by modern development techniques.

Stack Elements For The Request-Response Cycle Link

So, what are the stack elements that will help us reduce the requests forwarded to PHP? Well, two stack elements in particular will help us achieve that goal: the web server and the HTTP cache.

Web Server Link

We’ve been speaking quite a bit about web servers already. There are three big players in the web server space:

Together, these make up more than 90% of the market share of web servers on the Internet. We’re going to focus on Apache and nginx. While IIS can be used to run WordPress, it’s not common because it’s available only for Windows, and most WordPress servers use Linux.

This leaves us with Apache and nginx. For all of WordPress’ life, Apache has been the recommended web server. We had the LAMP stack (Linux, Apache, MySQL and PHP), which ran WordPress on both the computer and the server.

But behind the scenes, things were changing. There was a new player in town, and its name was nginx. Automattic and WordPress.com have been using it since 2008. It’s the web server that runs the largest percentage of high-traffic websites7 (a lot of which run WordPress). That’s why a lot of high-end hosting companies and top WordPress agencies use it as their web server.

It’s not that Apache is a bad web server. There are Apache experts who can make it run great under a lot of traffic. It just doesn’t do as well out of the box or with the standard WordPress configuration.

Meanwhile, nginx’s sole purpose is to handle a lot of traffic. That’s why Igor Sysoev8 started the project when he was working at Rambler9.

One of the reasons why nginx handles more traffic better is that it uses FastCGI10 to communicate with PHP. What is FastCGI? It’s a protocol that lets PHP run as a service separate from the web server.

Apache doesn’t do this by default. Each time the web server receives a request, it needs to start a PHP runtime process — even for images, JavaScript and CSS. This reduces the number of requests that the server can handle and how fast it can handle them.

This goes against one of the goals of the modern WordPress server stack, which we saw earlier. The stack needs to keep the request-response cycle time as low as possible. Loading PHP for every request, even when it doesn’t need it, goes against this goal. So, if you use Apache, look into FastCGI.

HTTP/211 is another important web server feature you should know about. It’s the next version of HTTP, the protocol that powers our entire request-response cycle.

Before the arrival of HTTP/2, a browser could have only six connections to the web server. And each connection could handle only one request at a time. So, in practice, a request-response cycle was capped at six requests per cycle.

That’s a real problem. Most websites have dozens of requests in their cycle. Developers and system administrators found clever ways to get around this limitation.

One of the better-known workarounds is the practice of combining CSS and JavaScript files. In an ideal scenario, this would bring down the total number of requests for CSS and JavaScript files to two: one for JavaScript and one for CSS.

This isn’t necessary with HTTP/2. HTTP/2 allows an unlimited number of requests per connection. This allows all extra requests after the initial HTML response to happen at the same time.

This has huge performance implications. A lot of the work of optimizing the server stack centers on the request-response cycle. By reducing the number of cycles to only a handful, HTTP/2 has done a tremendous amount of work for us.

HTTP Cache Link

The most important part of the modern WordPress server stack is the HTTP cache. In the WordPress world, we also call this page caching. The purpose of the HTTP cache is to cache responses to requests. What does this mean?

Well, let’s go back to our earlier example. The browser sends a request for the home page of modern.wordpress-stack.org, and the web server receives that request and forwards it to PHP.

The problem with this scenario is that the web server is dumb. It’ll always forward all requests it receives to PHP — regardless of whether most of the requests would generate the same response.

This is exactly what happens when visitors aren’t logged in. To the web server, they’re all different requests, but it doesn’t care. It will forward them all to PHP, which will generate the same response for all of them.

That’s terrible! As we saw earlier, PHP is the real bottleneck of our request-response cycle. Your browser can’t send its follow-up requests until it receives that initial home page response. We can’t have the web server forward everything to PHP by default.

That’s where the HTTP cache comes in. It sits between the web server and PHP. Its job is to check every request that the web server receives and look for a cached response. If there isn’t any, it’ll forward the request to PHP and then cache the response that PHP generates.

This drastically reduces the request-response cycle time, making the website load faster. It also lets the web server handle more simultaneous requests without blowing up.

The Different Flavors Of HTTP Cache Link

At this point, you should be wondering, “How can I get this baby on my server ASAP?!” The good news is that installing an HTTP cache on a WordPress server is quite easy. It’s the component with the widest range of options.

Install a Page-Caching Plugin Link

The easiest way is to install a page-caching plugin. You have a few options to pick from:

All but WP Rocket are available as free plugins in the WordPress directory. So, you can install one and test it out right away. That being said, of the four plugins, the best one is WP Rocket. While it’s a paid plugin, it does a lot more than just create an HTTP cache. These other benefits magnify the work that the HTTP cache is doing.

How Does a Page-Caching Plugin Work? Link

All of these plugins leverage a drop-in that WordPress has made available for caching. This caching drop-in lets the plugins create an HTTP cache system inside of WordPress. The caching drop-in needs two things to work.

First, the advanced-cache.php drop-in file needs to be in the wp-content folder. That’s the actual file. But unlike most WordPress drop-ins, this one doesn’t kick in by default. WordPress also needs the WP_CACHE constant to be true in order to load the drop-in. In most cases, you would set that in wp-config.php.

Plugin HTTP Cache (loading)18

The diagram above shows what happens when you enable the drop-in with a caching plugin. WordPress loads the drop-in in wp-settings.php during its loading process19. This is early enough in the process that WordPress hasn’t done anything time-consuming yet.

The caching plugin will then check whether it has already cached the response to the request. If it has, it will return that cached response. If it hasn’t, it will turn on PHP output buffering20, and WordPress will continue loading.

Now, output buffering is an interesting system. What it does is capture all the output from a PHP script in a string variable until one of two things happen:

  • you tell PHP to stop buffering its output using one of the built-in functions,
  • the PHP script finishes and needs to return a response to the browser.

The caching plugin is counting on the latter scenario. It wants WordPress to do its thing and then cache the whole output before PHP sends it back to the browser. You can see the process in the diagram below.

Plugin HTTP Cache (shutdown)21

Have the Web Server Do It Link

The next option is to add an HTTP cache at the web server level. The way it works is that the web server will cache all responses to requests that get forwarded to PHP. This solution is better than a caching plugin because it doesn’t need to touch PHP at all.

Web server HTTP cache
22

The diagram above gives an overview of what’s going in the web server. The web server receives a request and checks with the HTTP cache. If a response has been cached already, the HTTP cache will send that back.

Otherwise, it will forward the request to the PHP module (usually FastCGI). It will pass the request to WordPress so that it can generate a response. The HTTP cache module will then cache that response on the way back.

Both Apache and nginx come with the ability to add an HTTP cache system. The nginx one is built in. The Apache one is a separate module23 that you need to add to your Apache installation.

There isn’t a lot of information on how to use the Apache module with PHP or WordPress. That might be because it’s not popular with the Apache crowd, or maybe because it has some issues. There’s at least one long-standing issue24 with it that is still open.

Meanwhile, the nginx HTTP cache system is robust and well documented. You can use it as a normal HTTP cache25 or as a smaller yet effective micro-cache26. It’s just one more reason why nginx is the preferred web server nowadays.

Add Varnish to the Stack Link

What is Varnish27? It’s a dedicated HTTP cache server (or, as its developers like to call it, HTTP accelerator). Most high-traffic websites and premium hosting companies use it as their HTTP cache solution.

They use it because it’s powerful and offers the most flexibility. Varnish has its own configuration language, called VCL. It lets you control every element of the caching process. Varnish also comes with a lot of tools for analyzing what the cache is doing and how it’s performing.

These are the major differences between using it and just using the built-in web server HTTP cache. The built-in web server HTTP cache is super-performant but also pretty basic. You don’t have a lot of control beyond a few configuration options.

Nevertheless, this power and flexibility come at a price. Varnish is also the most complicated HTTP cache option. It does nothing but cache HTTP responses. It doesn’t handle SSL termination28, which most WordPress developers want (or should want). This means that our modern WordPress server stack is going to be more complex when we use it.

Varnish HTTP cache29

The diagram above illustrates this extra complexity. We now have two more components in our WordPress server stack: Varnish and a reverse proxy30.

The reverse proxy is there to overcome the limitation that Varnish has with SSL. It sits in front of Varnish and decrypts the requests that our server receives. You can also call this type of reverse proxy an SSL termination proxy31. The proxy then sends these decrypted requests to Varnish to process.

Once a request hits Varnish, the VCL configuration file(s) kick in. They’re Varnish’s brain. For example, they tell it how to:

  • analyze, clean up and modify incoming requests;
  • look for a cached response;
  • analyze, clean up and modify returning responses from WordPress;
  • cache these returning responses;
  • handle a request to remove one or more responses from the cache.

This last one is especially important. Left to itself, Varnish has no way to know when WordPress wants to remove a page from the cache. So, by default, if you make changes to a post and update it, visitors will keep seeing the same cached page. Luckily for us, a plugin exists32 that removes pages from the Varnish cache.

WordPress Link

All right, our request for the home page of modern.wordpress-stack.org has hit WordPress. It went through the request-response cycle that we just covered. The HTTP cache did everything it could to find an HTTP response to send back.

But there was no cached HTTP response to send back to the browser. At that point, the HTTP cache had no other choice. It had to forward the HTTP request to WordPress.

It’s all in WordPress’ hands now. WordPress has to turn our HTTP request into an HTTP response and send it back to the HTTP cache. As we saw earlier, this is the main bottleneck of our whole modern WordPress server stack.

The cause of this bottleneck is two-fold. WordPress has a lot PHP code to execute. This is time-consuming, and the slower PHP is at doing it, the longer it takes.

The other bottleneck is the database queries that WordPress needs to perform. Database queries are expensive operations. The more there are, the slower WordPress gets. This will be the focus of the last section on the query-result cycle.

Optimizing The PHP Runtime Link

Let’s get back to PHP. At this moment, WordPress has a minimum requirement of PHP 5.2. This version of PHP is almost 10 years old! (The PHP team stopped supporting it in 2011.)

The PHP team hasn’t been sitting idle all those years. Numerous performance improvements have been made, especially over the last few years. Let’s look at what you can do to optimize it nowadays.

Use the Latest Version of PHP Link

The easiest thing you can do is upgrade your version of PHP. Versions 5.4, 5.5 and 5.6 all saw performance improvements. The largest improvement was from 5.3 to 5.4. Switching to it increased the performance of WordPress by a decent amount.

Install Opcode Caching Link

Opcode caching is another way to speed up PHP. As a server-side scripting33 language, PHP has a big flaw: It needs to compile a PHP script each time it executes it.

The solution to this problem is to cache the compiled PHP code. That way, PHP doesn’t have to compile it each time it executes it. This is the job of the opcode cache34.

Before PHP 5.5, PHP didn’t come bundled with an opcode cache. You had to install it yourself on the server. This is another reason why using a more recent version of PHP is better.

Switch to a Next-Generation Compiler Link

The last thing you can do is switch to one of the two next-generation compilers: either Facebook’s HHVM35 or PHP 736, the latest version of PHP. (Why PHP 7? It’s a long story.)

Facebook and the PHP team built these two compilers from the ground up. They wanted to leverage more modern compilation strategies. HHVM uses just-in-time compilation37, whereas PHP 7 uses ahead-of-time compilation38. Both offer incredible performance improvements39 over good ol’ PHP 5.

HHVM was the first one to arrive on the scene a few years ago. A lot of top-tier hosts have had a lot of success with it, offering it as their primary PHP compiler.

It’s worth stressing, though, that HHVM isn’t an official PHP compiler. It’s not 100% compatible with PHP. The reason is that HHVM isn’t just designed to support PHP; it is also a compiler for Facebook’s Hack40 programming language.

PHP 7 is an official PHP compiler. It hasn’t been around for a long time. The PHP team released it in December of 201541. This hasn’t prevented some WordPress hosting companies from supporting it already.

The good news is that WordPress itself is 100% compatible with both compilers! The bad news is that not all plugins and themes are, because the minimum PHP version for WordPress is still 5.2.

Nothing is forcing authors to make their plugins or themes work with these compilers. So, you can’t go all in with one of them. Your stack should always fall back to PHP 5.

Query-Result Cycle Link

At this point, the PHP runtime is going through all of the WordPress PHP files and executing them. However, these WordPress PHP files don’t contain any data. They only contain the WordPress code.

The problem is that WordPress stores all of its data in a MySQL database. So, to get to it, the PHP runtime needs to query that database. The MySQL server returns the result of that query, and the PHP runtime then continues to execute the WordPress PHP files… well, that is, until it needs data again.

This back and forth can happen from a few dozen times to a few hundred times. (You might want to speak with your developer if it’s the latter!) That’s why it’s a major bottleneck.

Optimizing The Query-Result Cycle Link

The optimization goal here is to speed up the execution time of WordPress files by PHP. This is where database queries are problematic. They tend to take more time than just running plain PHP code (unless your code is doing something outrageous).

The obvious way to fix this problem is to reduce the number of queries that WordPress needs to perform. And that’s always worthwhile! But it’s not something the modern WordPress server stack can help with.

We might not be able to reduce the number of queries that WordPress makes, but we aren’t out of options either. There are still two ways that the stack can help us optimize the query-result cycle. It can reduce the number of queries made to the database in the first place. And for those queries that make it to the database, it can decrease the time it takes to run them.

These two options are both meant to do the same thing: make PHP wait as little as possible for results from the database, which will make WordPress itself faster.

Stack Elements For The Query-Result Cycle Link

Let’s look at the different stack elements involved in the query-result cycle. This part of the stack is less complex. But it still involves more than one component — namely, the MySQL database server and the object cache.

MySQL Database Server Link

A few years ago, a MySQL database server would mean the same thing to everyone. It was a server with the MySQL server42 installed. But things have changed a lot in recent years.

Various groups weren’t happy with how Oracle43 was managing the MySQL project. So, each group forked it and created its own version that you could “drop in” instead. The result is that there are now several MySQL database servers.

The new “official” MySQL server is the MariaDB server44. It’s the community-developed version of MySQL server. The community plans to maintain full compatibility with the MySQL server project.

Another popular alternative to MySQL is the Percona server45. Unlike MariaDB, Percona is more of a branch of MySQL. Its developers aren’t against the MySQL project itself; they just want to focus on improving MySQL’s performance. The MariaDB team later merged some of these performance improvements into the MariaDB project.

At the end of the day, you can pick the one you prefer. There’s no difference in performance between a Percona server and a MariaDB server (for most of us anyhow). They both perform better than MySQL. Percona does, however, maintain closer compatibility with the Oracle project.

What does affect performance is the storage engine46 that the WordPress database uses. The storage engine controls how the database server manages the data it stores. You can also set a different storage engine per database table; you don’t have to use the same one for the entire database.

A database server has several storage engines. We’re not going to look at all of them. Only two interest us: InnoDB47 and MyISAM48.

By default, WordPress uses the default MySQL database engine. Before MySQL 5.5, that engine was MyISAM. If you run a small WordPress website, then MyISAM is fine. MyISAM runs into performance issues once a website grows in size. At that point, InnoDB is the only choice for a database engine.

The only issue with InnoDB is that it requires some tuning to perform at its best. If you’re running a large database server, you might need to adjust things. Luckily for us, there’s a tool to help with that.

MySQLTuner49 is a small script that analyzes your database server. It will generate a report and give you tuning recommendations.

Object Cache Link

The brunt of the work of optimizing the query-result cycle lies with the object cache50. The job of the object cache is to store data that is time-consuming to get or generate. As you might guess, database queries are a perfect candidate.

WordPress uses the object cache a lot. Let’s say you use get_option51 to get an option from the database. WordPress will only query the database for that option once. It won’t query it again the next time someone needs it.

Instead, WordPress will fetch the query result from the object cache. This is a proactive step that WordPress takes to reduce the number of database queries that it needs to make. But it isn’t a foolproof solution.

While WordPress will do its best to leverage the object cache, a plugin or theme doesn’t have to. If a plugin or theme makes a lot of database queries and doesn’t cache the results, the stack can do nothing about it.

In such cases, most of the database queries will come from WordPress itself. So, you’ll get great mileage out of WordPress’s built-in use of the object cache. That’s why it’s an important element of the modern WordPress server stack.

Now, a problem with the object cache is that it doesn’t persist the data it stores by default. It just stores data in memory while PHP is executing all of the WordPress files. But once the PHP process terminates, all of the data that it stored in memory gets cleared.

This isn’t ideal at all. An object cache could stay valid for a long time, so you don’t want to limit it to a single request. The solution is to use a persistent object cache.

A persistent object cache often comes in the form of a plugin. That plugin would make use of the object-cache.php drop-in to do its job. This drop-in lets plugin authors change the default behavior of the object cache.

The plugins then connect the object cache to a persistent data store. They do that by replacing the fetch and save functionality of the default object cache. Instead of saving and fetching data to memory, the object cache does it from that store.

Persistent Object Cache Plugins Link

Nowadays, there are two popular data store options for persistent object caching:

Both of these data stores use RAM56 for storage, which makes them lightning-fast. In fact, their performance is comparable to that of the default object cache.

The only problem is that they don’t come preinstalled on servers. And neither does their PHP extension (which is optional with Redis). You need to install one before you can use the corresponding WordPress plugin.

Which one should you install? In practice, there isn’t much of a difference between the two for object caching. In the past, the popular option was Memcached. This has changed over the last few years. Redis has added a lot of features that have made it the go-to option for object caching.

Getting Your Own Modern WordPress Server Link

So, how do you get your own server? The obvious way is to get one from a top-tier WordPress hosting companies. These companies want to stay at the forefront of the WordPress hosting business, which motivates them to adopt the latest breakthroughs and technologies.

But what if you want one without breaking the bank? A couple of tools are available to anyone who would rather do it themselves and pay less for hosting. Let’s look at them.

DebOps for WordPress Link

DebOps for WordPress57 is a tool that I built to help anyone build a modern WordPress server. Its mission is to make the modern WordPress server stack available to anyone in the community58. That’s why I’m trying to make it as easy to use as possible. You don’t need any system administration knowledge to use it.

DebOps for WordPress configures a server with the following:

  • HHVM (until PHP 7 makes it into an official Linux repository)
  • MariaDB
  • nginx
  • Redis
  • Varnish

The tool does more than just configure a server with the latest technologies. It also takes care of securing the server for you. This is something that people often overlook when managing their own server.

EasyEngine Link

EasyEngine59 is a command-line tool designed to help you set up a WordPress website on a server. The great thing about EasyEngine is its flexibility: You can use it set up almost any combination of server technologies that we’ve looked at so far.

For example, it lets you set up a server with either HHVM or PHP 7. It lets you chose between Memcached and Redis for your persistent data store. And it lets you install administrator tools such as phpMyAdmin60.

It also offers a large number of options when it creates a WordPress website. You can tell it to set up a website with an HTTP cache using a plugin or nginx. All of this flexibility is why EasyEngine is such a popular tool.

Trellis Link

Trellis61 is a tool developed by Roots62. Like DebOps, it configures the server with a specific set of server technologies:

  • MariaDB
  • Memcached
  • nginx
  • nginx HTTP cache (optional)
  • PHP 7

One thing to know about Trellis is its relationship to Bedrock63, another tool built by Roots. Bedrock is a boilerplate for structuring a WordPress website around the “Twelve-Factor App64” principles.

The Roots team created Trellis to enable people to configure a server that uses Bedrock-structured WordPress website(s). You can’t use it with a normal WordPress installation, so keep that in mind.

Times Have Changed Link

As you can see, a WordPress server has a lot more moving parts today! But this doesn’t need to be a cause for despair. It’s not as bad as it looks because you don’t always need to use all of the parts.

That’s why so much of this article discusses how these parts work together. The point is to empower you to make your own decisions. Use this knowledge to decide which parts you need to use and when. In this way, you too will have a fast WordPress website.

(ms, al, il)

This article has first been published on Carl Alexander’s blog65.

Front page image credits: Pixabay66

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2016/05/WordPress-server-stack-diagram.png
  2. 2 https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_message
  3. 3 https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Response_message
  4. 4 https://en.wikipedia.org/wiki/Apache_HTTP_Server
  5. 5 https://en.wikipedia.org/wiki/Internet_Information_Services
  6. 6 https://en.wikipedia.org/wiki/Nginx
  7. 7 http://w3techs.com/blog/entry/25_percent_of_the_web_runs_nginx_including_46_6_percent_of_the_top_10000_sites
  8. 8 https://en.wikipedia.org/wiki/Igor_Sysoev
  9. 9 https://en.wikipedia.org/wiki/Rambler_(portal)
  10. 10 https://en.wikipedia.org/wiki/FastCGI
  11. 11 https://en.wikipedia.org/wiki/HTTP/2
  12. 12 https://wordpress.org/plugins/batcache/
  13. 13 https://wordpress.org/plugins/hyper-cache/
  14. 14 https://wordpress.org/plugins/cache-enabler/
  15. 15 https://wp-rocket.me/
  16. 16 https://wordpress.org/plugins/wp-super-cache/
  17. 17 https://wordpress.org/plugins/w3-total-cache/
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/05/Plugin-HTTP-Cache-loading-opt.png
  19. 19 https://carlalexander.ca/wordpress-adventurous-loading/
  20. 20 https://php.net/manual/en/outcontrol.setup.php
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/05/Plugin-HTTP-Cache-shutdown-opt.png
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/05/Web-server-HTTP-cache-opt.png
  23. 23 https://httpd.apache.org/docs/2.4/mod/mod_cache.html
  24. 24 https://bz.apache.org/bugzilla/show_bug.cgi?id=48364
  25. 25 https://www.nginx.com/blog/nginx-caching-guide/
  26. 26 https://www.nginx.com/blog/benefits-of-microcaching-nginx/
  27. 27 https://en.wikipedia.org/wiki/Varnish_(software)
  28. 28 https://www.varnish-cache.org/docs/trunk/phk/ssl_again.html
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/05/Varnish-HTTP-cache.png
  30. 30 https://en.wikipedia.org/wiki/Reverse_proxy
  31. 31 https://en.wikipedia.org/wiki/SSL_termination_proxy
  32. 32 https://en-ca.wordpress.org/plugins/varnish-http-purge/
  33. 33 https://en.wikipedia.org/wiki/Server-side_scripting
  34. 34 https://php.net/manual/en/intro.opcache.php
  35. 35 http://hhvm.com/
  36. 36 http://php7.zend.com/
  37. 37 https://en.wikipedia.org/wiki/Just-in-time_compilation
  38. 38 https://en.wikipedia.org/wiki/Ahead-of-time_compilation
  39. 39 https://wpengine.com/blog/php-7-the-way-of-the-future/
  40. 40 https://en.wikipedia.org/wiki/Hack_(programming_language)
  41. 41 http://php.net/archive/2015.php#id2015-12-03-1
  42. 42 https://en.wikipedia.org/wiki/MySQL
  43. 43 https://en.wikipedia.org/wiki/Oracle_Corporation
  44. 44 https://en.wikipedia.org/wiki/MariaDB
  45. 45 https://en.wikipedia.org/wiki/Percona_Server
  46. 46 https://en.wikipedia.org/wiki/Database_engine
  47. 47 https://en.wikipedia.org/wiki/InnoDB
  48. 48 https://en.wikipedia.org/wiki/MyISAM
  49. 49 http://mysqltuner.com/
  50. 50 https://codex.wordpress.org/Class_Reference/WP_Object_Cache
  51. 51 http://codex.wordpress.org/get_option
  52. 52 https://en.wikipedia.org/wiki/Memcached
  53. 53 https://wordpress.org/plugins/memcached/
  54. 54 https://en.wikipedia.org/wiki/Redis
  55. 55 https://wordpress.org/plugins/redis-cache/
  56. 56 https://en.wikipedia.org/wiki/Random-access_memory
  57. 57 https://github.com/carlalexander/debops-wordpress
  58. 58 https://carlalexander.ca/give-wordpress-an-apple-experience/
  59. 59 https://easyengine.io/
  60. 60 http://www.phpmyadmin.net/
  61. 61 https://roots.io/trellis/
  62. 62 https://roots.io/
  63. 63 https://roots.io/bedrock/
  64. 64 http://12factor.net/
  65. 65 https://carlalexander.ca/modern-wordpress-server-stack/
  66. 66 https://pixabay.com/en/cupcakes-wordpress-sweets-sweet-525513/

↑ Back to top Tweet itShare on Facebook

Carl has been coding since he was 8 years old. As of late, he has been doing mostly "web" stuff. A lot of it has been around PHP and WordPress. He's an organizer of the Montréal WordPress Group and WordCamp Montréal since 2010. He writes at carlalexander.ca.

  1. 1

    Hello,
    what do you think about Siteground’s caching plugin? It works well in my opinion…
    Thanks.

    0
    • 2

      I’d never heard of the SiteGround caching plugin before! I took a quick look at it and saw this warning “If you’re not hosted with SiteGround this plugin may not work because it relies on a specific server configuration.” I’d have to run some tests to see what works and what doesn’t, but I figure you’re probably safer with one of the other options.

      2
      • 3

        Chris Flannagan

        May 27, 2016 1:56 pm

        I used it for my companies website. It’s solid though they have implemented Google Pagespeed as an option in their caching section so I’ve switched to that and it’s made google happy (google speed test passes with flying colors now).

        0
  2. 4

    Andrew Khan

    May 27, 2016 9:13 am

    As someone that strives to have the highest performance for each site launched – this ^ a million times this.

    Fantastic guide, covers pretty much every aspect.

    The most important part is always going to be your full page cache. WP Super Cache is fantastic and will on average bring page load down to around 80ms on a badly optimised server. It’s almost as fast as serving static HTML files (partly because it basically is)

    5
  3. 5

    Steven Antonucci

    May 27, 2016 7:26 pm

    All of this about WordPress and nginx is fine, but the truth is that LiteSpeed Technologies customers report that the LiteSpeed WordPress caching solution is easily 2X faster and uses half the system resources. And there is noproxy set-up or third party cache, since LSWS caches, handles HTTP/S/2, and can be deployed across an entire WordPress farm as a load balanced cache layer.

    -1
    • 6

      Ron Jankins

      May 27, 2016 9:12 pm

      Steven, Litespeeds cache is actually quite a bit faster even than that and I have proven it pretty decisively. I really think it should be considered a major player, especially when IIS is listed.

      What other Webserver + cache can you slam with almost 4 million hits / pageviews in a few hours and not make a noticeable difference in performance on a shared webhosting plan? Answer is none as far as I my testing has showed.

      The numbers are pretty clear, take a look here where I performance test a web host running Litespeed + Lscache (kickassd) and also another running a stack of Apache + Nginx + memcached + Varnish. (Cloudways VPS). It is astonishing how much difference there is:

      https://roastahost.com/wordpress-hosting-performance-comparison/

      The guys at Litespeed have been putting a lot of time and effort lately into their caching and it shows.

      0
    • 8

      There are two problems with LiteSpeed and why it’s not mentioned in this article.

      First, it isn’t free. Yes, they have a free version. But you need the enterprise version to use the WordPress plugin.

      Second, it’s not what most hosts are using. I felt it was important to discuss what was happening right now. Of course, there are a few small hosts with it like Ron mentioned in his review. But the majority aren’t using it. Maybe they will in the future.

      0
  4. 9

    This guide is really perfect evidence that WordPress (and, by extension, PHP) is badly broken. If you need to do that much mucking around to get decent performance, something is wrong with the whole system. Sure, you can mess up performance on any platform with your own code and plugins, but even a barebones WordPress install has horrible performance and generates hopelessly unoptimized HTML (which is difficult to customize given that WordPress likes to generate its HTML in mysterious ways).
    Hint: Try Umbraco or another decent CMS that’s already optimized rather than messing around with a blog engine that thinks it’s a CMS.

    -2
    • 10

      wpcraftsman

      June 5, 2016 1:52 pm

      Yeah bud, about that. WordPress doesn’t ‘generate html’. The output is entirely dependant on the theme and/or any plugins you install. So if your WordPress site is generating “hopelessly unoptimized HTML,” it’s either because you wrote it that way, or you picked a theme that was created by someone just as clueless as you are.

      3
  5. 11

    mat gargano

    May 29, 2016 3:56 pm

    This article is so well put together. Thanks!

    BTW, if you think that PHP is a mess, I’d humbly like to say it’s because of the way that the HTML and the HTTP protocol was created… HTML was not made to be what it has become but there’s been tons of creativity and ingenuity (highlights: CSS, JavaScript, XMLHttpRequest, HTML5, CSS3, etc. to improve the frontend, and a clever set of mechanisms on the backend (http caching, object caching etc.) to get us from the browser that was essentially a stateless set of interlinked documents to the application to end all applications.

    Just my two cents :)

    2
  6. 12

    George Gkouvousis

    May 29, 2016 9:49 pm

    Carl, does DebOps support SSL termination proxy for https requests’ caching (at least out of the box) ? What’s your suggestion when it comes to SSL caching and the decision between your DebOps project / Easy Engine & Trellis ?

    0
    • 13

      Maciej Delmanowski

      May 31, 2016 9:08 am

      Hi. At the moment only nginx is supported out of the box by DebOps, however I hope that HAproxy will be added in the future. The PKI infrastructure should be able to handle it with a small modification to implement custom OCSP setup required by HAproxy.

      0
    • 14

      All these solution offer SSL termination. I’m the only one using a termination Proxy because I’m the only one using Varnish. Varnish doesn’t support SSL so you need the SSL termination proxy for the setup to work.

      Trellis and EasyEngine use nginx page caching instead of Varnish. This means that they can put everything in the same vhost. They don’t need a SSL termination proxy to handle HTTPS traffic.

      0
  7. 15

    Scott Richardson

    May 30, 2016 1:14 am

    It’s interesting, but even with all these advances to the server stack, WP websites still can’t beat a simple, custom coded site in PHP. There’s something about WP that slows it down – probably the insane amount of javascripts and resources common templates like to load?

    0
    • 16

      Rendering performance is different topic in itself! I could send you every file in 10ms, but, if it takes 3 seconds for Chrome to render the DOM, then it’ll feel slow anyways.

      0
  8. 17

    Shaun Murray

    May 31, 2016 6:01 pm

    I think it’s worth pointing out that this is a WordPress stack for a server running a single tenant If you were building a shared hosting server with multiple tenants, this would be insecure and too fragile to maintain.

    Most shared hosts will be running PHP as a CGI so that they know which user is running which naughty script, usually using suPHP so no opcode caching. FastCGI is of limited benefit as most servers can’t afford to keep enough FastCGI processes running that each user would see a benefit.

    The suggestion above of using LiteSpeed or I would add CloudLinux’s mod_lsapi (essentially litespeed’s API for Apache) gives you the security needed AND the performance AND is much easier to maintain and support.

    2
  9. 18

    What do you think of WPengines setup?

    0
  10. 19

    Brilliant write-up, very comprehensive and covers all the essentials – thanks.

    0

↑ Back to top