WordPress Redis Object Cache: Measure First, Because Often The Answer Is No.

We measured 70 to 77 queries per page at 8 to 15 milliseconds. On that site an object cache saves nothing a visitor could notice.

Aditya Sharma·9 min read

Short answer: a wordpress redis object cache is genuinely valuable on sites with authenticated traffic, stores, or measured query time above roughly 100 milliseconds. On an ordinary brochure site behind a working page cache it adds a service that can fail in order to save time nobody was losing.

The measurement takes ten minutes and decides it for you.

Measuring before deciding

Table of measured queries per page load on a WordPress install with WooCommerce. The homepage runs 70 queries in 14.3 milliseconds, the shop page 77 in 10.7 milliseconds, and a post 76 in 7.6 milliseconds
Measured with SAVEQUERIES on 7 September 2026. Total database time is between 8 and 15

milliseconds per request. A perfect object cache can only ever remove a portion of that.*

On this site, the honest recommendation is to do nothing. Nobody perceives eight milliseconds.

On a site running 400 queries taking 300 milliseconds, the identical change is worth a project. The technique is the same and its value differs by two orders of magnitude, which is exactly why this decision should not come from a checklist.

Measure it yourself by adding define('SAVEQUERIES', true); to wp-config.php temporarily, then reading $wpdb->num_queries and the summed query time on shutdown. Turn it off afterwards, as it stores every query in memory and is itself a performance problem on a busy site.

What a WordPress Redis object cache actually changes

Table comparing default WordPress against Redis or Memcached. Both cache objects within a request. Only the persistent cache survives to the next request or is shared between web servers. It rarely helps logged-out cached pages and clearly helps logged-in users, carts, checkouts and admin
The last two rows are the real argument. A full-page cache already protects anonymous

visitors by not running PHP at all. An object cache earns its keep on the requests a page cache cannot serve.*

Default WordPressRedis / Memcached
cache within one requestyesyes
cache survives to the next requestnoyes
shared between web serversnoyes
helps logged-out cached pagesn/ararely, a page cache already skipped PHP
helps logged-in users, cart, checkout, adminn/ayes, these bypass the page cache entirely

This is the point most often missed. WordPress already caches objects in memory within a single request. Redis makes that cache persist between requests and be shared across servers.

So the benefit lands on requests that actually execute PHP, which on a well-cached brochure site is almost none of them, and on a store is nearly all the ones that matter.

When it is worth it

Table of situations. WooCommerce stores with logged-in traffic, membership and LMS sites, measured query time above 100 milliseconds, and multi-server setups are all yes. Brochure sites with anonymous traffic and a working page cache, and sites with single-digit millisecond query time, are no
An object cache is another service that can fail, fill up, or serve stale data after a

deploy. On a site that does not need it, that is added risk for no return.*

SituationVerdict
yesWooCommerce store with real logged-in trafficcarts and checkouts hit the database every time
yesmembership or LMS sitealmost every request is authenticated
yesquery time measured above ~100msreal time to recover
yesmultiple web servers behind a load balancera shared cache is the only way they agree
nobrochure site, anonymous traffic, page cache workingalmost nothing reaches PHP to benefit
noquery time in single-digit millisecondsadding a moving part to save nothing

Installing Redis and measuring the actual before and after

Everything above describes what an object cache should do. I wanted the actual number, so I installed Redis against a real WordPress install on our test rig, rather than cite the mechanism and leave the size of the effect to the imagination.

wp plugin install redis-cache --activate
wp config set WP_REDIS_HOST lab-redis-1
wp redis enable
wp redis status   # Status: Connected, Drop-in: Valid, Ping: PONG

With the drop-in connected and confirmed, I requested the homepage with SAVEQUERIES on and read the query count off a response header on each request:

RequestObject cacheQueries
1st (cold, cache just enabled)on138
2ndon14
3rdon14
4thon14
baseline, cache disabledoff142

Queries dropped from 142 to 14 once Redis had something in it to serve, a reduction of roughly 90%. That is close to the largest effect this technique can plausibly produce, and it is real, measured on an actual request rather than asserted from how the mechanism is supposed to work.

The honest second half of the result is the wall-clock time for the same requests, and it is the more important number for this post’s argument:

RequestObject cacheTotal time
1st (cold PHP, no cache)off0.740s
2ndoff0.196s
3rdoff0.141s
1st (warm cache)on0.211s
2ndon0.201s
3rdon0.179s

A 90% cut in query count did not produce anything close to a 90% cut in response time. Once the first request past PHP’s own startup cost is excluded, the cached and uncached timings sit in the same rough band, 0.14 to 0.21 seconds, on this specific install. That is not a failure of Redis, it is exactly what the query measurement earlier in this post already predicted: this test site’s queries were fast to begin with, single-digit to low-double-digit milliseconds each, so removing 90% of them removes 90% of a number that was never large enough for a visitor to notice in the first place. The query count is a mechanism metric. The wall-clock time is the one a visitor experiences, and this test is a clean demonstration of why the two do not move together in lockstep, which is the entire argument this post opened with.

Testing the case this post says matters most

The homepage test above is close to the “no” case this post describes: anonymous, cacheable, low query count to begin with. The more relevant test for the “yes” case is a request that always executes PHP regardless of any page cache, so I measured the WooCommerce Store API cart endpoint, which is session-scoped and, per that post’s own testing, never served from a cache:

curl -s -o /dev/null -D - "http://localhost:8080/wp-json/wc/store/v1/cart" | grep -i x-db-queries
RequestObject cacheQueries
baselineoff152 (cold), 138, 138
warmon14, 14, 14

The same roughly 90% reduction as the homepage test, on an endpoint that, unlike the homepage, cannot be served by a page cache on a real production site with real carts in them. This is the case the “when it is worth it” table earlier in this post names directly: carts and checkouts hit the database on every single request, with no page cache available to intercept any of them, which means the query-count savings measured here translate much more directly into time a real visitor experiences, unlike the homepage case where a page cache would have intercepted almost all of that traffic before PHP ever ran.

The comparison between these two tests, run on the identical Redis setup minutes apart, is the cleanest illustration this post can offer of its own central claim: the mechanism produces the same roughly 90% query reduction whether or not the request matters, and whether that reduction is worth the operational cost of running Redis depends entirely on how much of a site’s real traffic looks like the second test rather than the first.

If you do install one

Three things that cause the support tickets.

Set a memory limit and an eviction policy. A Redis instance with no maxmemory will grow until something else on the server suffers. allkeys-lru is the usual choice for a cache.

Flush it on deploy. Stale cached objects after a plugin update produce genuinely baffling behaviour: the code is new, the data is old, and nothing in the site explains why.

Check it is actually connected. Every object cache plugin has a status screen, and a status screen is a claim rather than a measurement. Confirm the query count actually dropped, the same way you would confirm a page cache is doing anything at all.

The wider point

Object caching is the clearest example of a performance change that gets applied because it is on a list rather than because it was measured. It is the same instinct that leads to cleaning a database that was never the bottleneck.

Start with where the time is going. If server think time is already low, the database is not your problem and no cache will make the page feel faster.

Protuno’s free audit reports server response time from the domain alone, which tells you whether there is anything here worth investigating before you install anything. Straight with you as on every post here: Dash, the Performance agent, is built and named but not live yet.

Measure the query count on one client site this week. If it comes back under 20 milliseconds, you have just saved yourself a project.

What running this test actually took

Worth being specific about the setup, because it is smaller than the phrase “set up a Redis benchmark” suggests, and it is the kind of test worth running against a real client site’s staging copy rather than trusting a number from this post.

A single docker run redis:7-alpine container, joined to the same network as the WordPress install, and three WP-CLI commands to point the Redis Object Cache plugin at it. No production traffic, no risk to anything live, torn down again the moment the numbers were recorded. The entire test, install through cleanup, took a few minutes, which is worth knowing if the only thing standing between you and a real measurement on a client site is the assumption that benchmarking a cache requires more infrastructure than it actually does.

The mu-plugin doing the actual measurement was five lines: one hook printing the query count onto a response header on send_headers, nothing more elaborate than that. get_num_queries() is a core WordPress function, available on every install without any plugin at all, and reading it through a custom header rather than a debugging plugin’s UI meant the measurement could be pulled with plain curl, scriptable and repeatable rather than read off a screen by hand.

Why the two tests told different stories from the same cache

It is worth sitting with the gap between the homepage result and the cart endpoint result a second time, because it is the actual argument of this post compressed into two rows of a table rather than a paragraph of reasoning.

Both requests saw the same object cache, connected to the same Redis instance, and both saw close to the same proportional reduction in query count once the cache was warm. If query count were the only number that mattered, the two tests would carry identical advice: install Redis, save 90% of your database queries, done. But a page cache already exists in front of the homepage on any well-configured site, intercepting the overwhelming majority of real homepage requests before PHP, and by extension the object cache, ever gets involved at all. The cart endpoint has no such interception available to it, by design, because a cart has to reflect what is actually in it.

That is the distinction the “what it actually changes” table earlier in this post is trying to make in the abstract, and running both tests back to back on the same infrastructure is what makes it concrete rather than theoretical. The mechanism does not know or care which kind of request it is serving. It reduces queries by roughly the same proportion either way. Whether that reduction matters to a single visitor depends entirely on whether a page cache was already going to intercept the request before an object cache ever got the chance to help, which is a question about the specific site’s traffic pattern, not about Redis.

Comments