In this article, we will explore each of the components that make up the optimized WordPress hosting stack, point out a few potential pitfalls, and explain how each of the components work. Our goal: to get a potential WordPress site owner or webmaster up-to-speed on the important points of this new platform and provide tools to tackle potentially more complex challenges they might later encounter.
WordPress Hosting Stack Overview
Those already familiar with cPanel, the popular web hosting control panel, will feel right at home. Still at the heart of each server, cPanel allows simple (but powerful) control over everything from email account creation to SSH key management. Site owners can add domains, subdomains, and parked domains via the cPanel interface, and the Apache and NGINX configurations will reflect these changes.
NGINX handles all inbound requests for each website. It checks each incoming request for a match in the domain’s page cache. If it finds a match, the cached page displays for the site visitor. In so doing, the server does not have to run any PHP code or execute MySQL queries, making for a speedy response. When possible, NGINX directly serves static assets (such as CSS, scripts, and images).
On the other hand, should NGINX fail to find a cached page matching the request, it passes the request along to Apache and waits for the response. Apache continues to serve as the origin for site content, meaning you can continue to use
.htaccess files (e.g., permalinks and redirects will work without a problem, in most cases). Next, the server passes page requests along to a PHP-FPM pool allocated for each domain. The PHP-FPM pool delegates the request to an available worker that executes the actual PHP code (such as WordPress itself). The server then feeds the result back up the chain, and NGINX saves a copy of the response in its cache, speeding up future requests.
- ➊ User’s web browser makes request to NGINX to fetch a webpage.
- ➋ If NGINX fails to find a cached version of the page, or the page has been excluded from caching, NGINX requests the content from Apache.
- ➌ If a PHP script handles a page, Apache sends the request to the domain’s PHP-FPM pool. The PHP-FPM pool takes
.htaccessrewrites and other rules into account, allowing for the use of “pretty URLs” or permalinks.
- ➍ The PHP-FPM pool then dispatches the request to an available worker (or spawns a new worker if one is not available). The worker then executes the PHP code.
- ➎ The response travels back up, in reverse, through each of the previous steps, until it returns to the user’s web browser for display.
NGINX, a high-performance web server, can completely replace Apache or run alongside it in a reverse-proxy configuration. The WordPress Optimized stack uses the reverse-proxy configuration, meaning that NGINX requests the actual content from Apache. This configuration allows us to perform full-page caching, as well as serve static content (such as images and stylesheets) directly from NGINX. This results in significant speed increases and limits the number of connections to Apache. In other words, this configuration allows the server to deliver cached and static content to the user very quickly.
Caching: How it Works
As mentioned above, when a user visits a page on your website, NGINX first determines whether or not it has a page available in its cache. If so, it checks to see if that page remains valid and has not expired. Note, site owners can control this expiration period via the Cache Manager Plugin. By default, your site will set the expiration time to 4 hours. If a page does not exist in the cache, or you have identified it to the system as a page that should bypass the cache (like a login or checkout page), then the server sends the request to Apache and PHP-FPM, as illustrated above.
To determine which pages NGINX can cache, it examines the headers returned by the server. By default, NGINX ignores
Cache-Control headers. Many WordPress pages return a negative cache time, preventing pages from caching effectively. However, the NGINX Cache Controller plugin can send
X-Accel-Expires headers, which the server will use to set and enforce cache times for specific pages.
By default, certain pages will never cache — specifically, pages that send cookies or use PHP sessions. Therefore, where possible, have any cookies or other dynamic content load asynchronously (via
admin-ajax.php). In the Cache Manager Plugin, you also have the ability to match against cookies sent from the user’s browser. This allows us to bypass the cache for logged in users, or for users who have added an item to their shopping cart on a WooCommerce site, for example.
Clearing the Cache
When making changes to your site, or troubleshooting a problem, you may benefit from either clearing a single page or purging the entire cache. In either case, you can easily accomplish this via the Cache Manager Plugin. You can also quickly clear a single page from your browser by prepending
/purge to the URI portion. You will then see either a Purge Successful page, or a 404 Not Found page (indicating the page did not exist in the cache). The table below lists a few examples:
|https://example.com/||https://example.com/purge/||Purges the homepage for example.com|
|https://example.com/2017/01/cool-article||https://example.com/purge/2017/01/cool-article||Purges the page at |
An optimized PHP handler, PHP FastCGI Process Manager (PHP-FPM) provides high performance and lower latency page execution. It does this by maintaining and adjusting an on-demand pool of workers for each domain.
Each PHP-FPM master controls a group of pools, with each pool associated with a single domain or virtual host. Each of these pools then handles a group of workers — the processes that handle the actual execution of PHP code. When the server sends a request to a particular FPM pool, the pool delegates the work to an available worker or spawns a new worker if an existing one is not available (with the on-demand management type). This allows sites that receive a steady stream of traffic to load quicker, as there will typically be a worker available to handle the request. In addition, this architecture allows the workers to share a common pool of memory, permitting the use of opcode caching.
By default, your server enables Zend OpCache, PHP’s built-in opcode caching system, for PHP 5.5 and above. Opcode caching works by storing pre-compiled PHP code, which subsequent visitors can later execute again. This saves significant time, CPU usage, and I/O, since PHP does not need to re-interpret and re-compile your PHP code on every single execution.
When you add a new user or domain, the server uses the default PHP version. If you wish to experiment with a newer PHP version, or if your application requires an older PHP 5.x version, you can manually select these options from the MultiPHP Manager in cPanel. You can also configure custom PHP options via the MultiPHP INI Editor, or by creating a php.ini file.
Overall, this new platform should offer significant performance gains for most websites (compared to the previous Apache + suPHP stack). The addition of the Cache Manager Plugin will also allow users to further tweak the performance of their sites, to suit their particular needs.
Learn more from our WordPress Hosting Product Guide.