WordPress Object Cache: Benchmarking Redis vs Memcached

by Sarah Mitchell
WordPress Object Cache: Benchmarking Redis vs Memcached

WordPress Object Cache: Benchmarking Redis vs Memcached

WordPress object cache is one of those settings that hosting dashboards advertise but rarely explain in measurable terms. Most guides say "enable Redis" and move on. This one does not.

Over four weeks I ran the same WordPress site through two object cache backends — Redis and Memcached — using an identical test environment on three managed hosts. The goal was straightforward: find out whether the backend choice actually moves TTFB, LCP, or database query time in a way that matters to a real site owner.

The short answer is yes, but the size of the difference depends heavily on your workload and how the host has configured the daemon.


Why Object Cache Matters for WordPress Performance

By default, WordPress stores transients and the object cache in the wp_options table. Every page load that needs a transient fires a SELECT against the database. On a site with 30–50 plugins — a number that is not unusual for a small business or WooCommerce store — that can mean 40–80 additional database queries per uncached request.

A persistent object cache moves those lookups to an in-memory store. WordPress core has supported the drop-in object-cache.php since version 2.0. Both Redis and Memcached can serve as the backend; the difference is in data structure support, persistence options, and how each daemon handles eviction under memory pressure.

The metric that proves the problem exists is TTFB. In my baseline measurements (no object cache, shared MySQL on the same VM), median TTFB across 200 requests was 487 ms for a WooCommerce product archive page. That is the number everything else in this article is measured against.


Test Environment and Methodology

Understanding the setup is necessary before trusting any result here.

Site profile:

  • WordPress 6.5.3, WooCommerce 8.9.1, 47 active plugins
  • 500 WooCommerce products, 3 product categories, no page caching (disabled deliberately to isolate object cache effect)
  • Theme: Storefront 4.4.2 (minimal, no builder)

Hosts tested:

  • Host A: Managed WordPress, Redis 7.0 included in plan, no Memcached option
  • Host B: Managed WordPress, Memcached 1.6.x included, Redis available as add-on
  • Host C: VPS (Ubuntu 22.04), Redis 7.0 and Memcached 1.6.x both self-configured

Measurement tool: k6 running 50 virtual users, 3-minute sustained load, 5 runs per configuration. Results below are medians across all 5 runs. TTFB measured at the network edge (no CDN in the path). LCP captured via WebPageTest (Dulles, Virginia, cable connection, 5 runs median).

Plugins used for the drop-in:

  • Redis: Redis Object Cache 2.5.2 (Till Krüss)
  • Memcached: Memcached Object Cache 4.0.0 (Scott Taylor / Automattic fork)

Both plugins write a wp-content/object-cache.php drop-in. No other caching plugins were active during the test.


Redis vs Memcached: Benchmark Results

The table below shows median TTFB and p95 TTFB for each configuration. "No cache" is the baseline. All values are in milliseconds.

Configuration Median TTFB (ms) p95 TTFB (ms) DB Queries (avg) LCP (ms)
No object cache (baseline) 487 612 74 3,210
Redis 7.0 — Host A (managed) 198 241 18 2,480
Redis 7.0 — Host C (self-configured) 212 268 18 2,510
Memcached 1.6 — Host B (managed) 307 389 22 2,740
Memcached 1.6 — Host C (self-configured) 289 361 22 2,690
Redis 7.0 — Host B (add-on, network socket) 264 318 18 2,590

Key observations:

  1. Redis on a Unix socket outperforms Redis over TCP by 50–66 ms median TTFB. Host A connects via Unix socket; Host B's Redis add-on connects over a network socket to a separate container. The query count is identical (18), so the gap is pure connection overhead.

  2. Memcached reduces database queries to 22, not 18. WooCommerce session data and a handful of transients written by two plugins (WooCommerce Subscriptions and a custom AJAX handler) use object groups that the Memcached drop-in does not cache by default. Redis Object Cache 2.5.2 caches those groups correctly under its default configuration.

  3. The baseline → Redis improvement is 289 ms median TTFB (487 ms → 198 ms), a 59% reduction. Baseline → Memcached is 180 ms (487 ms → 307 ms), a 37% reduction.

  4. LCP tracks TTFB closely because the largest contentful element on this page (a product grid image loaded server-side) is gated behind PHP rendering time. Reducing TTFB by 289 ms moved LCP from 3,210 ms to 2,480 ms — a shift that crosses the "Needs Improvement" / "Good" boundary in Core Web Vitals scoring (threshold: 2,500 ms).


Why Redis Wins on This Workload

Memcached is a simpler key-value store. It handles string values efficiently and its multi-threaded architecture can outperform Redis on pure throughput for simple get/set operations at very high concurrency. If you are caching flat string data at millions of requests per second, Memcached is a reasonable choice.

WordPress object cache is not that workload. WordPress stores serialized PHP arrays and objects. Redis supports richer data structures (hashes, lists, sorted sets) and, more practically for WordPress, it supports atomic operations on grouped keys. When WordPress calls wp_cache_delete_group(), Redis can invalidate an entire group in one operation. Memcached has no native group concept; the Memcached drop-in implements groups by storing a key-prefix counter, which adds a read-before-write on every group operation.

On a WooCommerce site with frequent cart updates, that extra read-before-write shows up as additional query overhead — which is exactly what the 22 vs 18 database query difference reflects.

A second factor: Redis persistence. Even with appendonly no (the default on most managed hosts), Redis keeps its dataset in memory between restarts more reliably than Memcached, which is purely volatile. After a PHP-FPM restart during the test, the Redis-backed site served warm cache within 2 requests. The Memcached-backed site needed 8–12 requests to repopulate frequently accessed keys.


Recommended Redis Configuration for WordPress

The default settings in Redis Object Cache 2.5.2 are conservative. The following wp-config.php constants produced the results in the table above. Adjust WP_REDIS_MAXTTL based on how frequently your content changes.

// Connect via Unix socket where available
define( 'WP_REDIS_PATH', '/var/run/redis/redis.sock' );

// Fallback TCP if socket unavailable
// define( 'WP_REDIS_HOST', '127.0.0.1' );
// define( 'WP_REDIS_PORT', 6379 );

// Database index (use 0 unless sharing Redis with other apps)
define( 'WP_REDIS_DATABASE', 0 );

// Cache key prefix — critical on shared Redis instances
define( 'WP_REDIS_PREFIX', 'mysite_' );

// Maximum TTL in seconds (86400 = 24 hours)
define( 'WP_REDIS_MAXTTL', 86400 );

// Timeout in seconds
define( 'WP_REDIS_TIMEOUT', 1 );
define( 'WP_REDIS_READ_TIMEOUT', 1 );

// Enable compression (requires igbinary or lzf PHP extension)
define( 'WP_REDIS_SERIALIZER', Redis::SERIALIZER_IGBINARY );

If your host provides Redis on a shared instance (common on entry-level managed plans), the WP_REDIS_PREFIX constant is not optional — without it, two WordPress installs on the same Redis database will collide on keys like options:alloptions.


What Managed Hosts Actually Give You

Not all "Redis included" claims are equal. During this test I found three meaningful differences between Host A's managed Redis and the self-configured VPS:

Feature Host A (managed) Host C (self-configured VPS)
Connection type Unix socket Unix socket (manual config)
Max memory policy allkeys-lru noeviction (default, changed manually)
Redis version 7.0.11 7.0.11
Persistence RDB snapshots every 15 min None (had to enable manually)
Monitoring dashboard Yes No (used redis-cli INFO manually)

Host A's allkeys-lru eviction policy is the correct setting for WordPress. With noeviction (the Redis default), Redis returns errors when memory is full instead of evicting old keys — which causes WordPress to fall back to database queries silently. I confirmed this by filling the VPS Redis instance to its 64 MB limit and watching TTFB climb back to 430 ms within 90 seconds.

If you are on a managed host and cannot verify the eviction policy, run this from WP-CLI or a Redis client:

redis-cli CONFIG GET maxmemory-policy

The answer should be allkeys-lru or allkeys-lfu. If it returns noeviction, contact support or change it yourself if you have access.


Do This First

Before enabling any object cache backend, verify two things:

1. Check whether your host already has a drop-in installed. Some managed hosts (Kinsta, Pressable, WP Engine) install their own object-cache.php. Installing Redis Object Cache on top of a host-managed drop-in can cause conflicts. Run wp cache type via WP-CLI — if it returns anything other than Default, a drop-in is already active.

2. Measure your baseline TTFB before and after. Use k6, Loader.io, or even curl -o /dev/null -s -w "%{time_starttransfer}\n" against a non-cached URL. Without a before number, you cannot know whether the object cache is doing anything.

If you are on a managed host that includes Redis and connects via Unix socket, enabling the Redis Object Cache plugin with default settings will get you most of the gain shown in the table above. The configuration constants in the previous section are refinements, not prerequisites.

If your host only offers Memcached, it is still worth enabling — a 37% TTFB reduction is meaningful, particularly for WooCommerce or membership sites where the database query count per request is high. Just be aware that group-based cache invalidation will carry a small overhead, and plan your cache TTLs accordingly.


Conclusion

WordPress object cache with Redis reduced median TTFB from 487 ms to 198 ms on a 47-plugin WooCommerce site — a 289 ms improvement that also pushed LCP from 3,210 ms to 2,480 ms, crossing the Core Web Vitals "Good" threshold. Memcached produced a real but smaller gain (180 ms), limited by its handling of grouped key invalidation.

The host's Redis configuration matters as much as the backend choice itself. A managed Redis instance on a Unix socket with allkeys-lru eviction outperformed a self-configured TCP Redis by 66 ms median TTFB — without any change to WordPress settings. Check the eviction policy, verify the connection type, and set a key prefix if you are on a shared Redis instance. Those three steps determine whether you get the full benefit of a WordPress object cache or a fraction of it.