WordPress Object Cache: Redis vs Memcached Benchmarked

by Sarah Mitchell
WordPress Object Cache: Redis vs Memcached Benchmarked

WordPress Object Cache: Redis vs Memcached Benchmarked

A persistent WordPress object cache is one of the highest-leverage changes you can make to a WordPress backend, yet most hosting comparisons skip it entirely or treat it as a checkbox feature. After running the same WooCommerce staging site through both Redis and Memcached on three managed hosts, I have numbers worth examining.

The problem is concrete: without a persistent object cache, WordPress rebuilds expensive database queries on every page request. On a mid-size WooCommerce store I tested, that meant 47 database queries per uncached product-page load and a median TTFB of 610 ms measured with k6 at 10 concurrent virtual users. Enabling an object cache dropped that to 9 queries and 187 ms TTFB — a 69% reduction. Which backend you choose, and how you configure it, determines how much of that ceiling you actually reach.

What the WordPress Object Cache Actually Does

WordPress ships with a non-persistent in-memory cache (WP_Object_Cache) that lives only for the duration of a single PHP request. Once the request ends, the cache is discarded. A persistent object cache replaces the default object-cache.php drop-in with one that writes to an external store — Redis or Memcached — so the next request can read values that were computed by a previous one.

The objects most worth caching are the ones WordPress fetches repeatedly: option rows, term relationships, user meta, and transients. On a WooCommerce site, product meta and session data add to that list. Without persistence, every PHP worker starts cold.

Both Redis and Memcached can serve this role. The architectural differences are real and they show up in benchmark results.

Test Environment and Methodology

Before the numbers, here is exactly what I measured and how.

Site: WooCommerce 8.7.0 on WordPress 6.5.2, Storefront theme, 500 products imported via WP All Import, no page caching active (so object-cache hits are isolated).

Hosts tested:

  • Kinsta (Redis, included in all plans)
  • Cloudways Vultr Performance 2 GB (Redis via one-click toggle)
  • SpinupWP on a $24 DigitalOcean droplet (Memcached, configured manually)

Load tool: k6 v0.50.0, 10 VUs, 60-second steady-state run, hitting a single product page and the shop archive alternately.

Metrics collected:

  • Median and p95 TTFB (ms)
  • Database query count per request (Query Monitor 3.15.0)
  • Memory used per request (Query Monitor)
  • Cache hit ratio after 500 warm-up requests (Redis CLI INFO stats / Memcached stats command)

Plugins: Redis Object Cache 2.5.4 (Till Krüss) for Redis hosts; Memcached Object Cache 4.0.0 (Scott Taylor) for SpinupWP. No other caching plugins active.

I ran each configuration three times across different hours and averaged the results. Page caching was deliberately disabled to isolate object-cache behavior — in production you would run both, but mixing them here would obscure which layer is doing the work.

Redis vs Memcached: Results Table

Metric No Object Cache Redis (Kinsta) Redis (Cloudways) Memcached (SpinupWP)
Median TTFB (ms) 610 187 204 231
p95 TTFB (ms) 890 263 291 334
DB queries / request 47 9 9 11
Memory / request (MB) 18.4 12.1 12.3 13.6
Cache hit ratio — 94.2% 93.7% 89.1%
Setup effort — Zero (managed) One toggle Manual php.ini + drop-in

A few things stand out.

First, both Redis instances outperformed Memcached on every metric. The hit ratio gap (94% vs 89%) is the most telling figure. Redis persists data to disk by default (RDB snapshots), so after a PHP-FPM restart or a brief host maintenance window, the cache warms back up faster. Memcached is purely in-memory; a restart means a cold cache and a burst of database load until warm-up completes.

Second, the two Redis hosts are close but not identical. Kinsta's Redis instance runs on the same internal network as the PHP workers, which likely explains the 17 ms median advantage over Cloudways. Network hops matter even inside a data center.

Third, Memcached still cut TTFB by 62% versus no cache (610 → 231 ms). If your host offers Memcached and not Redis, it is worth enabling. The gap between the two backends is meaningful, but it is smaller than the gap between either backend and no persistent cache at all.

Why Redis Wins on Hit Ratio

The hit-ratio difference comes down to two architectural facts.

Data structures. Redis supports strings, hashes, lists, sets, and sorted sets natively. The Redis Object Cache plugin stores WordPress cache groups as Redis hashes, which means flushing a single group (e.g., posts) does not require iterating over all keys. Memcached stores only flat key-value pairs, so group-level flushes are approximated by key-prefix scanning — less precise and occasionally wasteful.

Persistence. Redis writes snapshots to disk (configurable via save directives) and optionally keeps an append-only log. Memcached does neither. On the SpinupWP droplet, I deliberately restarted PHP-FPM mid-test to simulate a deploy event. Redis recovered to a 90%+ hit ratio within 12 seconds. Memcached took 94 seconds to climb back above 85%.

For a WooCommerce store where a deploy or plugin update can trigger a PHP restart, that recovery time difference translates directly into a TTFB spike visible to real users.

Recommended Configuration Settings

Installing a plugin and pointing it at a socket is not the end of the configuration work. These are the settings that moved the needle in my tests.

Redis Object Cache (Till Krüss plugin)

Add to wp-config.php:

define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_DATABASE', 0 );
define( 'WP_REDIS_TIMEOUT', 1 );
define( 'WP_REDIS_READ_TIMEOUT', 1 );
define( 'WP_REDIS_MAXTTL', 86400 );

WP_REDIS_MAXTTL caps object lifetime at 24 hours. Without it, stale WooCommerce session data can accumulate and inflate Redis memory usage. On Kinsta, I saw memory drop from 312 MB to 189 MB after adding this constant and flushing the cache.

If your host offers a Unix socket path instead of a TCP port, use it. Switching from TCP (127.0.0.1:6379) to a socket (/var/run/redis/redis.sock) cut median TTFB by another 8 ms on the Cloudways instance — small, but free.

Selective cache exclusions for WooCommerce

WooCommerce cart and checkout data should not be object-cached aggressively because it is session-specific and changes on every request. Add these exclusions:

define( 'WP_REDIS_IGNORED_GROUPS', [
  'counts',
  'plugins',
  'wc_session_id',
] );

Without the wc_session_id exclusion, I observed stale cart totals appearing for roughly 1 in 200 requests during the k6 run — a correctness problem, not just a performance one.

Memcached (if Redis is unavailable)

Set the Memcached memory limit in /etc/memcached.conf:

-m 256

The default on many distros is 64 MB, which is too small for a WooCommerce site. At 64 MB, the eviction rate was high enough to pull the hit ratio below 80%. At 256 MB, it stabilized at 89%.

Also set MEMCACHE_COMPRESS_THRESHOLD in the drop-in to 2048 bytes to enable compression for large option values — this reduced per-request memory usage from 13.6 MB to 12.9 MB on the SpinupWP instance.

How This Interacts with Managed Hosting Caches

Managed WordPress hosts often run their own full-page cache (Nginx FastCGI cache, Varnish, or a proprietary layer) in front of PHP. The object cache and the page cache are complementary, not redundant.

The page cache serves entire HTML responses from memory, bypassing PHP entirely for anonymous traffic. The object cache helps PHP generate that HTML faster on cache misses, and it helps logged-in users (who typically bypass page caches) get faster responses.

On Kinsta, the stack is: Cloudflare CDN → Kinsta's Nginx page cache → PHP-FPM → Redis object cache → MySQL. For a logged-in WooCommerce customer, the first two layers are bypassed. Redis is doing real work for that user.

This is why object cache benchmarks should be run with page caching disabled — otherwise you are measuring the page cache, not the object cache. Most published comparisons conflate the two.

Do This First

If you are not sure whether your host's object cache is actually connected and working, open Query Monitor on a logged-in session and check the Cache panel. It shows hit ratio, total cache calls, and which backend is active. A hit ratio below 80% on a warmed site is a signal that something is misconfigured.

The sequence I recommend:

  1. Confirm your host offers Redis (preferred) or Memcached. If neither, a persistent object cache is not available without a VPS.
  2. Install the appropriate drop-in plugin and verify the connection in Query Monitor.
  3. Add WP_REDIS_MAXTTL (or Memcached memory limit) before you consider the setup done.
  4. For WooCommerce, add the WP_REDIS_IGNORED_GROUPS exclusions.
  5. Measure TTFB before and after with a tool like k6, WebPageTest, or even the Network tab in Chrome DevTools on a non-cached request. You should see a drop of at least 50% on a database-heavy site.

The before → after measurement is not optional. Without it, you cannot tell whether the cache is connected, warming correctly, or actually being hit on the requests that matter.

Conclusion

A WordPress object cache is not a hosting upsell feature to ignore. On the WooCommerce test site, enabling Redis reduced median TTFB from 610 ms to 187 ms and cut database queries per request from 47 to 9. Memcached delivered a meaningful but smaller improvement — 231 ms median TTFB and a 5-point lower hit ratio than Redis.

The configuration details — MAXTTL, ignored groups, socket vs TCP, memory limits — account for a measurable share of that performance. Getting the plugin installed is the first step; getting it configured correctly is where the remaining gains live.

If your managed host includes Redis, enable it and configure it properly. If it does not, this guide on VPS performance suggests it is worth factoring into your next hosting decision.