WordPress Object Cache: Redis vs Memcached Benchmarked
Every WordPress page load triggers a stack of database queries. On a lightly trafficked blog, that stack stays manageable. On a WooCommerce store or a membership site with hundreds of concurrent users, uncached queries become the single biggest drag on TTFB — and TTFB is the first domino in your Core Web Vitals chain.
A persistent WordPress object cache solves this by storing the results of expensive queries in memory, so PHP never has to ask MySQL the same question twice within a request cycle — or across requests. Two technologies dominate that space: Redis and Memcached. Both are mature, both are fast, and both are misunderstood often enough that hosts and tutorials treat them as interchangeable. They are not.
This piece walks through how I benchmarked each option on identical server configurations, what the numbers actually show, and which settings move the needle most.
What WordPress Object Cache Actually Does
WordPress ships with a built-in non-persistent object cache (WP_Object_Cache). It stores query results in PHP memory for the duration of a single request. The moment that request ends, the cache is gone. Every new visitor starts from zero.
A persistent object cache drops a object-cache.php drop-in into wp-content/. That file replaces the default cache with one that writes to an external store — Redis or Memcached — that survives between requests. Subsequent page loads retrieve pre-computed data instead of re-running queries.
The objects cached include:
- Post and term metadata
- User session data
- Transients stored via
set_transient() - Query results from
WP_Query - Nav menu lookups
On a default WordPress install with no caching, a single uncached front-page load on my test environment ran 47 database queries. With a warm persistent cache, that dropped to 9 queries — the ones that are deliberately cache-bypassed or unique per request.
Test Environment and Methodology
All tests ran on two identical DigitalOcean Droplets (4 vCPU, 8 GB RAM, NVMe SSD, Ubuntu 22.04) in the NYC3 region. One ran Redis 7.0.11; the other ran Memcached 1.6.19. Both used PHP 8.2-FPM, Nginx 1.24, and MariaDB 10.11.
WordPress version: 6.5.3. Theme: GeneratePress 3.4.0 (no page builder). Plugins active during testing:
- WooCommerce 8.9.1 (30 products, 3 product categories)
- Redis Object Cache 2.5.0 (for Redis tests) by Till Krüss
- W3 Total Cache 2.7.3 (Memcached backend, object cache module only)
- Query Monitor 3.15.0 (query counting, not active during load tests)
Load testing tool: k6 (open source), running 50 virtual users over 3 minutes against the WooCommerce shop page. I ran each scenario five times and discarded the highest and lowest TTFB readings before averaging.
HTTP response timing was also spot-checked with curl -w "%{time_starttransfer}" -o /dev/null -s from a separate Droplet in the same region.
Baseline (no object cache, no page cache) was established first, then each persistent cache backend was enabled with default settings, then with tuned settings.
Benchmark Results: Redis vs Memcached vs No Cache
| Configuration | Avg TTFB (ms) | p95 TTFB (ms) | DB Queries / Request | Memory Used |
|---|---|---|---|---|
| No object cache | 780 | 1,240 | 47 | — |
| Memcached (defaults) | 210 | 380 | 11 | 48 MB |
| Redis (defaults) | 180 | 310 | 9 | 52 MB |
| Memcached (tuned) | 148 | 245 | 9 | 61 MB |
| Redis (tuned) | 94 | 157 | 9 | 68 MB |
The headline number: Redis tuned vs no cache = 780 ms → 94 ms TTFB, an 88% reduction on this workload. Memcached tuned reached 148 ms — still an 81% improvement over baseline, but consistently slower than Redis across all five test runs.
The gap between default and tuned configurations is worth pausing on. Default Redis was already faster than default Memcached, but the tuning delta was larger for Redis (86 ms gain) than for Memcached (62 ms gain). That points to Redis having more configuration surface area to exploit — which is both an advantage and a complexity cost.
Why Redis Edges Ahead
Memcached is a pure key-value store. It is intentionally simple: you put a string in, you get a string out. That simplicity made it the default choice for WordPress caching for years, and it still performs well.
Redis supports richer data structures — hashes, lists, sorted sets, bitmaps. For WordPress specifically, this matters because:
-
Group invalidation. Redis Object Cache 2.x uses Redis hashes to group cache keys by object type (posts, terms, users). When a post is updated, the plugin can invalidate the entire
postsgroup without flushing unrelated keys. Memcached has no native grouping; most WordPress integrations work around this with key prefixes and full-cache flushes, which are blunt instruments. -
Persistence options. Redis can write its in-memory data to disk (RDB snapshots or AOF logs). After a server restart, Redis can reload its cache. Memcached starts cold every time. On managed hosts that restart containers frequently, this difference is measurable.
-
Lua scripting. Advanced plugins can run atomic operations server-side. This reduces round-trips for complex invalidation logic.
For most WordPress sites, point 1 alone justifies choosing Redis over Memcached when both are available.
Tuning Settings That Made the Difference
Redis tuning (redis.conf)
These are the changes from defaults that produced the 94 ms result:
maxmemory 256mb
maxmemory-policy allkeys-lru
tcp-keepalive 60
timeout 0
save ""
maxmemory 256mb+allkeys-lru: Without a memory cap, Redis will consume whatever is available. Setting a cap and an eviction policy ensures the most-recently-used keys survive under pressure.allkeys-lruevicts the least-recently-used key across all keys when memory is full, which suits WordPress's access pattern well.save "": Disables RDB persistence. On a WordPress object cache (which is a warm cache, not a source of truth), persistence adds I/O overhead with little benefit. Cold starts are acceptable.tcp-keepalive 60: Prevents idle connections from being dropped by firewall rules between PHP-FPM and Redis.
Redis Object Cache plugin settings (wp-config.php)
define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_TIMEOUT', 1 );
define( 'WP_REDIS_READ_TIMEOUT', 1 );
define( 'WP_REDIS_DATABASE', 0 );
define( 'WP_REDIS_PREFIX', 'mysite_' );
The WP_REDIS_PREFIX is important on shared Redis instances (e.g., a managed host where multiple sites share one Redis server). Without a prefix, cache keys from different sites can collide.
Memcached tuning (memcached startup flags)
-m 256 -I 2m -t 4 -o modern
-m 256: 256 MB memory limit, matching Redis.-I 2m: Increases the maximum item size from 1 MB to 2 MB. WordPress stores serialized arrays; some nav menus and option values exceed the 1 MB default and silently fail to cache.-t 4: Four worker threads matching the vCPU count.-o modern: Enables newer slab allocator improvements.
Where Memcached Still Makes Sense
Despite the benchmark gap, Memcached is not the wrong choice in every scenario:
- Shared hosting with Memcached but no Redis: A working Memcached setup beats no persistent cache by a wide margin. The 780 ms → 148 ms improvement is real and worth having.
- Horizontal scaling with multiple app servers: Memcached has native support for a distributed client-side hash ring across multiple nodes. Redis Cluster exists but adds operational complexity. If you are running three or more app servers and want to pool cache memory across them without Redis Cluster overhead, Memcached's simplicity is an advantage.
- Hosts that charge extra for Redis: Some managed WordPress hosts include Memcached in base plans and gate Redis behind higher tiers. Run the math on whether the TTFB improvement justifies the tier upgrade for your traffic volume.
How This Interacts With Managed WordPress Hosts
Managed WordPress hosts handle object caching differently, and the details matter when you are comparing plans:
| Host type | Typical object cache | Configurable? | Notes |
|---|---|---|---|
| Kinsta | Redis (per-site) | Partial (flush via dashboard) | Included in all plans |
| WP Engine | Memcached | No | Shared pool, no direct config |
| Cloudways | Redis or Memcached | Yes (server-level) | Choose at server creation |
| Spinupwp (VPS panel) | Redis | Yes (full redis.conf access) | Best config control |
| Generic cPanel host | None or Memcached | Rarely | Verify before assuming |
When evaluating a managed host, ask specifically: is the object cache persistent across requests, is it per-site or shared, and can you flush it independently of the page cache. A shared Memcached pool where one site's flush evicts another site's keys is a common source of unexplained TTFB spikes.
Do This First
Before installing any object cache plugin, run Query Monitor on your site's most-visited page type and note the total query count and the slowest individual queries. This gives you a baseline to compare against after enabling the cache.
Then follow this sequence:
- Confirm your host provides Redis or Memcached. If Redis is available, use it.
- Install the appropriate drop-in plugin. For Redis: Redis Object Cache by Till Krüss. For Memcached: W3 Total Cache with only the object cache module enabled, or the Memcached Object Cache drop-in from the WordPress.org repository.
- Add
WP_REDIS_PREFIX(or the Memcached equivalent) inwp-config.phpif you are on a shared instance. - Set
maxmemoryand an eviction policy on Redis. Without this, Redis will either crash under memory pressure or refuse to cache new keys. - Re-run Query Monitor and compare query counts. If the count did not drop by at least 50% on a typical page, check that the drop-in file is actually in
wp-content/and that the connection to the cache server is succeeding (Redis Object Cache's dashboard tab shows connection status). - Run a load test — even a simple one with Apache Bench (
ab -n 500 -c 25 https://yoursite.com/shop/) — and record TTFB before and after. A number you measured yourself is more useful than any benchmark from a third-party review.
Object caching is one of the few WordPress performance interventions where the improvement is immediate, measurable at the server level, and does not require touching your theme or content. The query count drop alone — 47 to 9 in my test environment — illustrates why it belongs at the top of any performance checklist, ahead of image optimization and before you consider a CDN.