WordPress Cache Expensive Query with Object Cache and Redis

By the time I decided to optimize some of my WordPress queries to be more efficient I was already using some caching techniques.

Most of my WordPress projects are hosted on my own Google Compute Engine based web-server on Debian. While static content is also delivered from a Cloudflare CDN.
So my normal setup was CDN -> Frontend Nginx -> proxy to Varnish -> Backend Nginx -> fastCGI PHP-fpm

It goes pretty fast on everything for non-logged-in users and performs well for logged-in, as static content is being cached, and varnish and fastcgi cache does a good job on dynamic content for optimized queries.

It turned out, I needed a feature to display random posts. Many articles related to WordPress, cover the topic, stating the usage for random posts:

$args = array(
'orderby' => 'rand',
);
query_posts( $args );

However, it’s rarely mentioned, that this query is an expensive one, and gets exponentially slow as the database grows.

WordPress Official Recommendations

I really wanted to display random posts, but didn’t want my sites to slow down, so I digged into the topic, and here is what WordPress itself recommends – WP Object Cache

If you read the article carefully, you will note, that while functions for object caching (query results are objects by the way), they are not active in WordPress by default, and you have to code your own solution or install a plugin.

Wordpress Caching Plugins List
WordPress Caching Plugins List

Besides, you need to wrap your expensive queries into a cache check functions:

$random = wp_cache_get( 'home_random' );
if ( false === $random ) {

$random_args = array(
'post_type' => 'post',
'orderby' => 'rand',
'posts_per_page' => $num,
'max_num_pages' => 1
);
$random = new WP_Query( $random_args );
wp_cache_set( 'home_random', $random, '', 86400 );
}

I knew I don’t need those queries to refresh often, so I used wp_cache_set with an expiration time of 86400 seconds (1 day).

Redis, PHP extension for Redis and WordPress plugin for Redis

As for the plugins, I know that industry is well accepting Redis software for caching, so I decided to give the Redis Object Cache plugin a go. However, note that it will only work if you are able to install redis with command line on your webserver, or your hosting provider has it installed for you. I followed this article for installation process.

After installation, you will also need a redis extension for php. For Debian use this in command line:

apt-get update
apt-get dist upgrade
apt-get install php-redis

Don’t forget to restart PHP after completing these steps!
In my case I have php 7.4 with FPM:

systemctl restart php7.4-fpm

Other recommendations

I had some specific to my usage issues, that you might not really encounter, however, here are some time savers for you:

  • If you have multiple domains on your webserver, you need to specify separate Redis database in your wp-config.php for each one. E.g.
define('WP_REDIS_DATABASE', 1);
  • In my case I’m also using Nginx rules for FastCGI caching, so I added some rules for random queries:
	
        if ( $query_string ~ "orderby=rand" ) {
		set $skip_cache 0;
	}	
	if ($args ~ "orderby=rand") {
		set $skip_cache 0;
	}

Did my article help you or am I doing something wrong? Please share your thoughts in comments section!

Follow Sam Tyurenkov:
Hi there, I'm a web-designer, marketing and product manager, business developer. I have created this website and about 25 others. I'm also doing various tasks for IT projects besides websites - like mobile games.