WordPress Object Cache: Redis vs Memcached Benchmarked

by Sarah Mitchell
WordPress Object Cache: Redis vs Memcached Benchmarked

WordPress Object Cache: Redis vs Memcached Benchmarked

Persistent object caching is one of the highest-leverage performance changes you can make to a WordPress site — yet most hosting comparisons skip past it entirely. Page caching gets the headlines; object caching does the quiet work of keeping your database from repeating the same queries on every request.

The two dominant backends are Redis and Memcached. Both are in-memory key-value stores. Both are supported by mature WordPress drop-in plugins. But when I ran the same WordPress stack against each one under controlled load, the TTFB difference hit 47% in Redis's favor on a WooCommerce product archive page. That number deserves an explanation, not just a headline.

This article walks through the test environment, the exact plugin configuration, the results table, and the settings that produced the best numbers.

Why Object Caching Matters for Core Web Vitals

WordPress generates pages dynamically. Even with a full-page cache in front, logged-in users, cart pages, and personalized content bypass that cache entirely. Every uncached request triggers a cascade of WP_Query calls, option lookups, and taxonomy fetches — most of which return identical data across requests.

The WordPress object cache API (wp_cache_get, wp_cache_set) stores those results in memory for the duration of a single request by default. A persistent backend extends that lifespan across requests. The practical effect: a WooCommerce site that was hitting 340 ms TTFB on its shop page dropped to 178 ms after enabling Redis with the right configuration. That 162 ms reduction is enough to move a borderline LCP score from "Needs Improvement" into "Good" on a mid-tier shared host.

LCP is the Core Web Vitals metric most directly affected because it measures when the largest visible element finishes loading. A slower TTFB delays the entire render chain — the browser can't parse HTML it hasn't received yet.

Test Environment and Methodology

All tests ran on a single VPS (4 vCPU, 8 GB RAM, NVMe SSD) running Ubuntu 22.04, Nginx 1.24, PHP 8.2-FPM (OPcache enabled), and MariaDB 10.11. WordPress 6.5.3 with WooCommerce 8.9.1 and a catalog of 500 products and 12 product categories.

Three configurations were tested in sequence, with a 10-minute warm-up period before each measurement run:

  • Baseline: WordPress default in-memory object cache (no persistent backend)
  • Memcached: 128 MB allocation, WP Memcached drop-in (object-cache.php from the official plugin, version 4.0.0)
  • Redis: 128 MB allocation, Redis Object Cache plugin by Till Krüss, version 2.5.4, using the PhpRedis extension

Load was generated with k6 running 50 virtual users over 3 minutes, targeting the WooCommerce shop page (/shop/) with no page cache active (Nginx fastcgi_cache disabled). Each virtual user was unauthenticated. TTFB was captured at the 50th and 95th percentiles. All three runs used the same MariaDB query cache settings (disabled, to isolate object cache effects).

LCP was measured separately using WebPageTest (Dulles, Virginia, Chrome, cable profile) with five runs per configuration, median reported.

Results: Redis vs Memcached vs No Cache

Configuration TTFB p50 (ms) TTFB p95 (ms) LCP (ms) DB Queries / Request
No persistent cache 341 612 2,840 48
Memcached 128 MB 243 398 2,290 31
Redis 128 MB (PhpRedis) 178 271 1,960 18

The headline number: Redis delivered a 47.8% lower p50 TTFB compared to no cache, and a 26.7% improvement over Memcached. The p95 gap is even wider — Redis at 271 ms versus Memcached at 398 ms, a 32% difference under higher concurrency.

Database queries per request tell the underlying story. The persistent object cache is intercepting more lookups as the cache warms, and Redis is intercepting more of them than Memcached. The likely cause is connection overhead: Memcached uses a pure PHP client in this configuration, while Redis uses the PhpRedis C extension, which has lower per-operation latency.

Why Redis Outperformed Memcached in This Stack

Three factors explain the gap.

1. Client library overhead. The Memcached plugin tested here uses the PHP Memcached extension (not memcache). That extension is compiled, but PhpRedis is generally faster for small, frequent get/set operations — which is exactly the access pattern WordPress generates. A 2023 benchmark by the Relay team (the authors of a Redis relay proxy) showed PhpRedis averaging 0.08 ms per operation versus 0.14 ms for the PHP Memcached extension under a WordPress-like workload.

2. Data structure support. Redis supports native lists, hashes, and sets. The Redis Object Cache plugin uses this to group cache keys by group, enabling efficient group-level invalidation without flushing the entire cache. Memcached has no native grouping; the plugin emulates it by storing an index key per group, which adds an extra round-trip per invalidation event.

3. Persistence and eviction policy. Redis was configured with maxmemory-policy allkeys-lru. When the 128 MB limit is approached, Redis evicts the least-recently-used keys rather than random keys. Memcached uses LRU by slab class, which can evict frequently-used small keys to make room for large values in the same slab. On a WooCommerce catalog, product meta values vary significantly in size, making Memcached's slab allocator less efficient.

None of this means Memcached is a poor choice. On a host where Redis is unavailable or where you're running a simpler site with a uniform cache key size distribution, Memcached will still cut your TTFB meaningfully versus no persistent cache — 28.7% in this test.

Recommended Redis Configuration for WordPress

These are the settings that produced the results above. Adjust maxmemory based on your server's available RAM; 128 MB is a reasonable floor for a single WordPress site.

redis.conf additions:

maxmemory 128mb
maxmemory-policy allkeys-lru
tcp-keepalive 60
save ""

Disabling save turns off RDB snapshots. For a pure object cache, persistence adds I/O overhead with no benefit — the cache is disposable by design.

wp-config.php additions:

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 constant is important if you run multiple WordPress installs on the same Redis instance. Without it, cache keys from different sites will collide.

Set WP_REDIS_TIMEOUT and WP_REDIS_READ_TIMEOUT to 1 second. If Redis becomes unavailable, WordPress will fall back to the in-memory cache after a 1-second wait rather than hanging the request.

Plugin settings (Redis Object Cache 2.5.4):

Enable "Client-Side Cache" only if you're running PHP 8.0+ and your Redis server supports client-side caching (Redis 6.0+). In testing, this reduced per-request Redis round-trips from an average of 34 to 21 on the shop page, contributing roughly 12 ms of additional TTFB improvement beyond what the table above shows — but it requires careful testing on your specific stack before enabling in production.

Recommended Memcached Configuration

If your host provides Memcached but not Redis, these settings minimize the gap.

memcached startup flags:

-m 128
-I 2m
-t 4

-I 2m increases the maximum item size to 2 MB. WordPress occasionally stores serialized arrays (navigation menus, widget data) that exceed the default 1 MB limit. When an item exceeds the limit, it silently fails to cache, and you lose the benefit for that key.

-t 4 sets the thread count to match the vCPU count. Default is 4 on most distributions, but verify with memcached -help.

wp-config.php additions:

define( 'MEMCACHED_SERVERS', [ 'default' => [ '127.0.0.1:11211' ] ] );

Which Hosts Provide Redis vs Memcached

Object cache backend availability varies significantly across managed WordPress hosts. This is based on documentation and direct testing as of June 2024.

Host Redis Memcached Notes
Kinsta Yes (included) No Redis enabled per-site from MyKinsta dashboard
WP Engine Yes (add-on) No Requires Global Edge Security or higher plans
Cloudways Yes (add-on) Yes (included) Redis costs $5–$15/month depending on size
Flywheel No No Full-page cache only; no persistent object cache
SpinupWP Yes (included) No Enabled per-site, PhpRedis extension pre-installed
RunCloud Yes (manual) Yes (manual) Both available; user installs and configures

SpinupWP and Kinsta are the two managed hosts where Redis is genuinely frictionless to enable — one toggle in the dashboard, correct object-cache.php drop-in installed automatically. On Cloudways, the add-on cost is worth factoring into your hosting comparison math: $5/month for 1 GB Redis is reasonable for a WooCommerce store, less so for a simple blog where full-page caching already handles most traffic.

Do This First

Before enabling any persistent object cache backend, run a query monitor baseline. The Query Monitor plugin (version 3.16.4 tested) shows per-request database query counts and which WordPress functions are generating them. If your uncached request count is under 20 queries, the gains from object caching will be modest. If you're seeing 40+ queries — common on WooCommerce, LMS, and membership sites — persistent object caching is the highest-ROI change you can make before touching anything else.

The sequence that works:

  1. Install Query Monitor, load your highest-traffic page type, record the query count and TTFB.
  2. Enable Redis (preferred) or Memcached, warm the cache with two or three page loads, then re-measure.
  3. Record the before and after numbers. If TTFB dropped by less than 15%, check whether your page cache is already intercepting most requests — in which case the object cache is only helping logged-in users and dynamic routes.
  4. Only after confirming object cache gains, layer in full-page caching (Nginx FastCGI cache, or this guide for plugin options) for the remaining uncached traffic.

The 341 ms → 178 ms improvement documented here came from a WooCommerce store with 48 queries per uncached request. That's a realistic number for a catalog site with a moderately complex theme. Your mileage will depend on your query count, but the methodology for measuring it is the same.