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
-
Sign Up for a Free Loader Account:
- Visit Loader.io (opens in a new tab) and sign up for a free account.
- After registering, you’ll be prompted to verify ownership of your website.
-
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
.
- Upload the file to your
-
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
-
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).
- In the Loader.io dashboard, create a new test and enter your website's URL (e.g.,
-
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:
-
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, whilesudo tee
adds the repository URL to your APT sources list. Then,sudo apt update
updates your package lists so Redis becomes available for installation.
- Explanation: This adds the official Redis package repository to your server, ensuring that you can install and keep Redis updated. The
-
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.
- Explanation: This command installs the Redis server on your system. The
-
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:
-
Access Your WordPress Admin Panel:
Log in to the WordPress admin panel by visitinghttps://example.com/wp-admin/
. -
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.
-
Enable Redis Object Cache:
- Go to Settings > Redis.
- Click the Enable Object Cache button to activate Redis object caching.
-
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:
-
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.
-
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
). Thelevels=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.
- Explanation: This command tells Nginx where to store the cached files and how much memory to allocate (
-
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).
- Explanation: These rules tell Nginx when to skip caching. For instance, POST requests (used when submitting forms) and pages with a query string (
-
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.
- Explanation: This block configures FastCGI caching for PHP requests. If
-
Save changes in Vim:
After
editing, press ESC
, type :wq
, and press Enter
to save and close the file.
Modify nginx.conf
-
Open the Nginx configuration file:
sudo vim /etc/nginx/nginx.conf
-
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. Theadd_header
directive allows you to check if the request was a cache hit (HIT
), miss (MISS
), or bypass (BYPASS
) by adding a custom header.
- Explanation: The
-
Save and exit Vim:
PressESC
, type:wq
, and pressEnter
. -
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.
- Explanation: The
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).
-
Install the Plugin:
- Go to Plugins > Add New and search for Nginx Helper.
- Click Install Now, then Activate.
-
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.
-
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.