WordPress-Server-Ubuntu-24.04
4 Object Cache and Page Cache

Configuring Redis Object Cache and Nginx FastCGI Page Cache for WordPress

In the previous lesson, we covered obtaining an SSL certificate, configuring Nginx for HTTPS, and setting up a database and WordPress site on a Linux server with a LEMP stack. To further enhance site performance, this chapter focuses on backend caching for WordPress. Caching boosts throughput (requests per second) and reduces response times (load times).


Initial Benchmarks: WordPress Performance Without Caching

To assess performance before implementing caching, we'll simulate traffic using an application called Loader. Loader allows you to simulate a large number of concurrent users, helping measure how the server handles traffic and track response times.

Setting Up a Free Loader Account

  1. Sign Up for a Free Loader Account:

  2. Verify Your Website Over HTTPS:

    • Loader.io will provide you with a token for verification.
    • You can verify your website by uploading the token file to your root directory or adding a DNS TXT record to your domain.
    • For file verification:
      • Upload the file to your /var/www/example.com/public_html/ directory.
      • Ensure that it is accessible over HTTPS by visiting https://example.com/loader-verification-file.txt.
  3. Verify the Website in Loader.io:

    • After uploading or updating DNS records, click Verify in the Loader.io dashboard to confirm ownership of your site.

Running a Test with Loader

  1. Create a Test:

    • In the Loader.io dashboard, create a new test and enter your website's URL (e.g., https://example.com).
    • Specify the number of users to simulate and the duration of the test (e.g., 250 users over 1 minute).
  2. Run the Test:

    • Execute the test, and Loader will simulate the specified number of users accessing your website simultaneously.
    • Review the results to see how your site performs under load, noting key metrics such as response time and requests per second.

Loader Test Results Breakdown

The server performance was tested with 250 clients over 1 minute on September 13th. Here is the breakdown of the key metrics from this test:

Response Time:

  • Average Response Time: 263 ms
  • Minimum Response Time: 98 ms
  • Maximum Response Time: 503 ms

This shows that the server was able to handle requests quickly, with minimal fluctuations between minimum and maximum response times. The overall average response time of 263 ms is well within acceptable performance standards for a well-optimized WordPress site.

Request Success Rate:

  • Successful Requests: 250
  • Timeouts: 0
  • Errors (400/500): 0
  • Network Errors: 0

This indicates that all requests were processed successfully, with no errors or timeouts during the test.

Bandwidth Usage:

  • Sent: 59.08 KB
  • Received: 20.27 MB

The bandwidth used during the test shows that a significant amount of data was successfully transmitted to users.

Redirects:

  • Valid Redirects: 250
  • Invalid Redirects: 0

All requests that required redirects were properly handled.

These results demonstrate that the server performed exceptionally well under the simulated traffic. The average response time of 263 ms indicates a fast, responsive site, and the absence of timeouts or errors suggests that the server is robust and capable of handling traffic efficiently.


Installing an Object Cache

An object cache stores database query results, reducing the need to query the database repeatedly. This significantly improves WordPress performance by avoiding redundant database queries.

Redis is a top-notch open-source option for object caching, though alternatives like Memcache and Memcached are also popular.

Installing Redis on DigitalOcean:

  1. Add Redis Package Repository and Update Package Lists:

    curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
    echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
    sudo apt update
    • Explanation: This adds the official Redis package repository to your server, ensuring that you can install and keep Redis updated. The curl command downloads the signing key, while sudo tee adds the repository URL to your APT sources list. Then, sudo apt update updates your package lists so Redis becomes available for installation.
  2. Install Redis Server and Restart PHP-FPM:

    sudo apt install redis-server -y
    sudo service php8.3-fpm restart
    • Explanation: This command installs the Redis server on your system. The -y flag automatically confirms the installation. After installing Redis, PHP-FPM (FastCGI Process Manager) is restarted to ensure PHP works smoothly with Redis.
  3. Ensure Redis Starts on Reboot:

    sudo systemctl enable redis-server
    • Explanation: This command ensures that the Redis server automatically starts when your server reboots. This is important to keep Redis running without needing manual intervention after reboots.

Installing the Redis Object Cache Plugin:

  1. Access Your WordPress Admin Panel:
    Log in to the WordPress admin panel by visiting https://example.com/wp-admin/.

  2. Install Redis Object Cache Plugin:

    • Navigate to Plugins > Add New and search for Redis Object Cache by Till Krüss.
    • Click Install Now, then Activate the plugin.
  3. Enable Redis Object Cache:

    • Go to Settings > Redis.
    • Click the Enable Object Cache button to activate Redis object caching.
  4. Verify Redis Status:

    • You can monitor Redis activity and cache status through the Redis settings page in the admin panel.
    • If needed, you can manually flush the cache from this panel.

Object caching reduces the number of database queries significantly, improving response times. For example, database queries may drop from 22 to 2 depending on the theme and plugins, and the average query time may reduce from 2.1ms to 0.3ms as measured by tools like Query Monitor.


Configuring a Page Cache

Object caching helps, but serving a static HTML version of pages can further reduce overhead. Nginx FastCGI cache can automatically cache static HTML versions, preventing PHP and MySQL from being hit on subsequent requests.

Setup Instructions:

  1. Modify your Nginx server block:

    sudo vim /etc/nginx/sites-available/example.com
    • Explanation: This opens your Nginx configuration file in Vim, a text editor. In this file, you’ll define caching rules for your site.
  2. Add the following to define the cache path:

    fastcgi_cache_path /home/user/example.com/cache levels=1:2 keys_zone=example.com:100m inactive=60m;
    • Explanation: This command tells Nginx where to store the cached files and how much memory to allocate (100m). The levels=1:2 configuration helps organize the cache directory structure into subfolders, making it more efficient to retrieve cached files. inactive=60m specifies that cache files will be stored for 60 minutes if they aren’t accessed.
  3. Add cache exclusions above the first location block:

    set $skip_cache 0;
     
    if ($request_method = POST) {
        set $skip_cache 1;
    }
     
    if ($query_string != "") {
        set $skip_cache 1;
    }
     
    if ($request_uri ~* "/wp-admin/|/wp-json/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
        set $skip_cache 1;
    }
     
    if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
        set $skip_cache 1;
    }
    • Explanation: These rules tell Nginx when to skip caching. For instance, POST requests (used when submitting forms) and pages with a query string (?parameter=value) should not be cached. We also exclude WordPress-specific admin pages (/wp-admin/), APIs (/wp-json/), and user-specific content (like logged-in users or cookies).
  4. Add the FastCGI cache settings inside the location block for PHP:

    location ~ \.php$ {
        fastcgi_cache example.com;
        fastcgi_cache_bypass $skip_cache;
        fastcgi_no_cache $skip_cache;
        fastcgi_cache_valid 60m;
    }
    • Explanation: This block configures FastCGI caching for PHP requests. If $skip_cache is set to 1, caching is bypassed. Otherwise, the page is cached for 60 minutes. fastcgi_no_cache prevents caching for the specified conditions.
  5. Save changes in Vim:
    After

editing, press ESC, type :wq, and press Enter to save and close the file.


Modify nginx.conf

  1. Open the Nginx configuration file:

    sudo vim /etc/nginx/nginx.conf
  2. Add caching key and headers:

    fastcgi_cache_key "$scheme$request_method$http_host$request_uri";
    add_header Fastcgi-Cache $upstream_cache_status;
    • Explanation: The fastcgi_cache_key defines how cached content is identified. The combination of the URL scheme ($scheme), HTTP method ($request_method), host ($http_host), and request URI ($request_uri) ensures unique cache entries for each page and request type. The add_header directive allows you to check if the request was a cache hit (HIT), miss (MISS), or bypass (BYPASS) by adding a custom header.
  3. Save and exit Vim:
    Press ESC, type :wq, and press Enter.

  4. Test and reload Nginx:

    sudo nginx -t
    sudo service nginx restart
    • Explanation: The nginx -t command tests the configuration for syntax errors. If everything is correct, the service is restarted to apply the changes.

Install the Nginx Cache Plugin

This plugin helps manage the Nginx FastCGI cache, allowing you to automatically purge cached content when it’s outdated (e.g., when a new post is published).

  1. Install the Plugin:

    • Go to Plugins > Add New and search for Nginx Helper.
    • Click Install Now, then Activate.
  2. Configure the Plugin:

    • Navigate to Settings > Nginx Helper and configure cache purging rules. You can purge the cache when posts, pages, or custom post types are updated, ensuring your users always see the latest content.
  3. Manually Purge Cache via SSH (if needed):

    sudo rm -rf /home/user/example.com/cache/*
    • Explanation: This command deletes all cached files, forcing Nginx to generate fresh cache files the next time users access the site.

WooCommerce FastCGI Cache Rules

Caching is beneficial, but for WooCommerce or similar e-commerce sites, avoid caching dynamic pages like the shopping cart, checkout, or account pages to prevent issues with user-specific content.

Add exclusions for WooCommerce pages:

if ($request_uri ~* "/(cart|checkout|my-account)/*$") {
    set $skip_cache 1;
}
 
if ($http_cookie ~* "woocommerce_items_in_cart") {
    set $skip_cache 1;
}

Modify the Nginx configuration file:

sudo vim /etc/nginx/sites-available/example.com

Add these exclusions below existing conditionals. Save changes and reload Nginx:

sudo nginx -t
sudo service nginx reload

By following these steps, you'll have a robust caching setup with Redis Object Cache and Nginx FastCGI Cache, ensuring your WordPress site is optimized for performance, even under high traffic loads.ginx reload


Check that the “fastcgi-cache” response header is set to “BYPASS” for WooCommerce pages or if an item is in the cart.

Similar exclusions may be necessary for other plugins like Easy Digital Downloads, WP eCommerce, BuddyPress, and bbPress. Each plugin should have documentation for adding caching rules.

---

### Final Benchmarks: Performance With Caching

After configuring caching, perform a final benchmark with a maximum of 750 concurrent users.

**Final Benchmark Results:**

The server handled [**insert your final benchmark results here**] with an average response time of **136ms**, showing significant performance improvement.