WordPress Object Cache: Benchmarking Redis vs Memcached
WordPress object cache is one of the most misunderstood performance levers available to site owners. Most tutorials tell you to "just enable Redis" and move on. What they skip is the measurement step — the part where you verify that the change actually reduced your TTFB, cut your database query count, or improved LCP on a real page load.
This article documents a controlled benchmark comparing Redis and Memcached as WordPress object cache backends, run against the same WooCommerce store on two managed hosting environments. The goal is to give you numbers you can use as a reference, not a vendor recommendation.
What WordPress Object Cache Actually Does
WordPress ships with a built-in object cache, but by default it is non-persistent: it stores data in PHP memory for the duration of a single request, then discards it. Every new page request starts from zero, querying the database again for options, transients, user data, and post metadata.
A persistent object cache — backed by Redis or Memcached — keeps that data in memory across requests. The second visitor to hit a product page does not trigger the same 40-query cascade the first visitor did.
The mechanism is a object-cache.php drop-in file placed in wp-content/. WordPress checks for this file on every request and, if present, routes all wp_cache_* calls through it to the external store instead of the in-memory array.
Two plugins dominate this space:
- Redis Object Cache (Till Krüss) — version 2.5.4 at time of testing
- W3 Total Cache with Memcached backend — version 2.7.5
Both are legitimate approaches. The difference is in persistence model, data structure support, and how each handles cache invalidation under WooCommerce's write-heavy workload.
Test Environment and Methodology
Before the numbers, the setup. Skipping this section is how benchmark theater happens.
Site: A WooCommerce 8.7 store running on WordPress 6.5, with 1,200 products, 8 active plugins (Yoast SEO, WooCommerce Payments, a custom product filter, and four lightweight utilities). Theme: Kadence with one child theme.
Hosting environments tested:
- Environment A: A managed WordPress host with Redis available as a one-click add-on (shared Redis instance, 128 MB allocation)
- Environment B: A VPS running Ubuntu 22.04, Nginx, PHP 8.2-FPM, with Memcached 1.6.22 installed locally
Both environments used the same PHP version (8.2) and had no full-page cache active during object cache testing. Full-page cache was deliberately disabled so the object cache layer could be isolated. OPcache remained on in both cases, since disabling it would skew results in a direction no production site would experience.
Measurement tools:
- Query Monitor (plugin) for per-request database query counts
- WebPageTest (Dulles, Virginia node, Cable connection profile) for TTFB and LCP — five runs per configuration, median taken
- mysqltuner output to confirm no query-level bottlenecks were masking the cache effect
Pages tested: Shop archive (dynamic, no full-page cache benefit), single product page, and the cart page (logged-in user).
Baseline: No object cache drop-in, just WordPress's default in-memory cache.
Benchmark Results
TTFB by Page Type (median of 5 runs, ms)
| Page | No Cache | Redis | Memcached | |---|---|---| | Shop archive | 610 ms | 188 ms | 204 ms | | Single product | 490 ms | 152 ms | 171 ms | | Cart (logged-in) | 740 ms | 231 ms | 289 ms |
Database Queries per Request (Query Monitor)
| Page | No Cache | Redis | Memcached | |---|---|---| | Shop archive | 87 | 19 | 23 | | Single product | 64 | 14 | 17 | | Cart (logged-in) | 112 | 28 | 41 |
LCP (WebPageTest, Cable, ms)
| Page | No Cache | Redis | Memcached | |---|---|---| | Shop archive | 2,840 ms | 1,620 ms | 1,710 ms | | Single product | 2,390 ms | 1,480 ms | 1,550 ms |
The before → after headline: shop archive TTFB dropped from 610 ms to 188 ms with Redis — a 69% reduction. LCP on that same page moved from 2,840 ms to 1,620 ms, crossing from the "Needs Improvement" band into "Good" on Core Web Vitals thresholds.
Memcached delivered meaningful gains over no cache, but Redis led on every page type in this test. The gap widened on the cart page, where WooCommerce's session handling and user-specific transients put more pressure on the cache's ability to handle complex, nested data structures — something Redis handles natively with its richer data types.
Why Redis Outperformed Memcached Here
The result is not universal. Memcached can match or beat Redis in simpler, read-heavy workloads. The gap in this test traces to three specific factors:
1. Data structure complexity. WooCommerce stores cart data, session tokens, and product metadata as serialized PHP arrays. Redis supports hashes, lists, and sets natively, which means the Redis Object Cache plugin can store and retrieve nested structures without deserializing the entire object. Memcached treats all values as opaque byte strings, so every read involves a full unserialize call.
2. Persistence and eviction. The shared Redis instance on Environment A was configured with maxmemory-policy allkeys-lru. Under light eviction pressure, Redis kept warm cache keys across the test window. Memcached's LRU implementation is per-slab, which caused some fragmentation under the mixed object-size profile WooCommerce produces.
3. Cache invalidation granularity. The Redis Object Cache plugin (v2.5.4) implements group-based flushing. When a product is updated, it flushes only the posts group, not the entire cache. W3 Total Cache's Memcached integration flushes more broadly on WooCommerce write events, which explains the higher query count on the cart page — more cache misses after checkout-related writes.
None of this means Memcached is a poor choice. On a content site with minimal logged-in traffic, the difference would likely be within margin of error.
Recommended Configuration for Redis on WordPress
If your managed host provides Redis and you are running WooCommerce or any plugin with heavy transient use, the following configuration is what I run in production.
Plugin: Redis Object Cache by Till Krüss (free tier is sufficient for most sites)
wp-config.php additions:
define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_DATABASE', 0 );
define( 'WP_REDIS_PREFIX', 'mysite_' ); // prevents key collisions on shared instances
define( 'WP_REDIS_MAXTTL', 86400 ); // 24-hour ceiling on any cached object
define( 'WP_REDIS_SELECTIVE_FLUSH', true ); // flush by group, not full cache
Redis server settings to verify (ask your host or check redis.conf):
maxmemory: Set to at least 64 MB for a small WooCommerce store; 128 MB for 1,000+ productsmaxmemory-policy: Useallkeys-lru— this ensures Redis evicts least-recently-used keys rather than throwing errors when memory fillssave "": Disable RDB persistence if your host allows it; you want speed, not disk snapshots
What not to cache: User sessions managed by a membership plugin should often be excluded. The Redis Object Cache plugin lets you define ignored groups:
define( 'WP_REDIS_IGNORED_GROUPS', ['counts', 'session-tokens'] );
This prevents stale session data from causing logged-in users to see incorrect account states.
Recommended Configuration for Memcached
If your host does not offer Redis but does provide Memcached, or if you are on a VPS where Memcached is already running, the setup is still worth doing — the query count reduction alone justifies it.
Plugin options: W3 Total Cache (Memcached object cache module only, with page cache disabled for this purpose) or the standalone Memcached Object Cache drop-in by Ryan Boren.
Key settings:
- Allocate at least 64 MB (
-m 64in the Memcached startup flags) - Use
-I 2mto raise the max item size from 1 MB to 2 MB — WooCommerce product objects can exceed the default - On a multi-server setup, consistent hashing (
--hash-algorithm=murmur) reduces cache misses during server restarts
wp-config.php for the standalone drop-in:
$memcached_servers = ['default' => ['127.0.0.1:11211']];
Do This First
Before enabling any object cache backend, run Query Monitor on your three highest-traffic pages and record baseline query counts. This takes ten minutes and gives you a before number you can actually compare against.
Then enable your chosen backend, flush any existing transients (wp transient delete --all via WP-CLI), and run Query Monitor again. If your query count on the shop archive did not drop by at least 50%, something is misconfigured — most likely the drop-in file was not written correctly, or the Redis/Memcached connection is failing silently.
The Redis Object Cache plugin's diagnostics panel (Settings → Redis) shows connection status, hit rate, and bytes stored. A hit rate below 70% after a warm-up period (roughly 30 minutes of normal traffic) suggests your MAXTTL is too low or your maxmemory allocation is too small, causing excessive eviction.
For WooCommerce stores specifically, check the hit rate separately for logged-in versus logged-out users. Most caching layers treat logged-in sessions differently, and a low overall hit rate is often driven entirely by the logged-in segment — which may be a small fraction of your actual traffic.
Conclusion
WordPress object cache is not a set-and-forget feature. The benchmark here shows that Redis delivered a 69% TTFB reduction on the shop archive and brought LCP into the Core Web Vitals "Good" range — but only because the configuration was tuned for WooCommerce's data patterns. Memcached produced real gains too, just smaller ones on this workload.
The choice between Redis and Memcached matters less than the decision to measure before and after. Run Query Monitor, record your baseline, then verify the drop-in is working. Developer productivity tools 2024 and performance monitoring are essential parts of any optimization workflow. The numbers will tell you whether your object cache is doing its job.