WordPress Object Cache: Redis vs Memcached Benchmarked
WordPress object cache is one of the least-discussed levers in performance optimization, yet it consistently delivers the largest TTFB reductions of any server-side change. On a WooCommerce store I migrated last quarter, enabling a persistent object cache dropped median TTFB from 340 ms to 61 ms — without touching a single line of theme code or changing the hosting plan.
Most tutorials stop at "install a plugin and enable Redis." This one goes further: it documents exactly how Redis and Memcached behave differently under WordPress workloads, which managed hosts support each, and what the benchmark numbers look like across three representative site types.
What the WordPress Object Cache Actually Does
WordPress ships with a built-in non-persistent object cache. Every page request builds that cache in memory, uses it during the request lifecycle, then discards it. The next request starts from zero.
A persistent object cache replaces that behavior by routing wp_cache_get() and wp_cache_set() calls to an external store — Redis or Memcached — that survives between requests. Subsequent requests for the same data skip the database entirely.
The performance impact scales with database query volume. A simple brochure site with 12 queries per page sees modest gains. A WooCommerce catalog page firing 180+ queries sees dramatic ones. That asymmetry is why benchmarking your specific site type matters more than any general recommendation.
Test Methodology
All tests ran on a single VPS (4 vCPU, 8 GB RAM, NVMe) running Ubuntu 22.04, Nginx 1.24, PHP 8.2-FPM, and MariaDB 10.11. WordPress 6.5 with no caching plugins active at baseline.
Three site profiles:
- Site A — Blog, 22 posts, Kadence theme, 8 active plugins, ~40 DB queries/page
- Site B — WooCommerce store, 320 products, Storefront theme, 14 plugins, ~160 DB queries/page
- Site C — Membership site, LearnDash, 900 enrolled users, logged-in requests only, ~210 DB queries/page
For Redis I used Redis 7.2 with the redis PHP extension (6.0.2) and the Redis Object Cache plugin by Till Krüss (version 2.5.4). For Memcached I used Memcached 1.6.23 with the memcached PHP extension (3.2.0) and the WP Memcached drop-in (bundled with W3 Total Cache 2.7.3, isolated so no other caching layers were active).
Load testing used k6 with 50 concurrent virtual users over a 3-minute ramp, measuring p50 and p95 TTFB. Each scenario ran three times; results below are median of the three runs. Pages served without full-page cache — only the object cache layer varied.
Redis vs Memcached: Benchmark Results
| Site | Baseline p50 TTFB | Redis p50 TTFB | Memcached p50 TTFB | Redis p95 | Memcached p95 |
|---|---|---|---|---|---|
| A (Blog) | 218 ms | 74 ms | 71 ms | 310 ms | 308 ms |
| B (WooCommerce) | 340 ms | 61 ms | 88 ms | 490 ms | 390 ms |
| C (Membership, logged-in) | 410 ms | 58 ms | 104 ms | 620 ms | 480 ms |
A few things stand out.
On Site A, both backends are statistically equivalent. Forty database queries is a low enough volume that the overhead of either external store is comparable to the savings. The 3 ms difference is inside measurement noise.
On Sites B and C, Redis pulls ahead — not because of raw read speed (Memcached is marginally faster at single-key lookups in isolation) but because of two WordPress-specific behaviors:
1. Group invalidation. WordPress stores cache keys in logical groups (posts, terms, users). When a post is updated, the entire posts group is invalidated. Redis supports atomic group deletion via a single DEL on a pattern or via tagged sets. Memcached has no native group concept; the common workaround is a "key prefix versioning" trick that requires an extra round-trip per cache read to fetch the current version key before retrieving the actual value. Under high write concurrency (WooCommerce order processing, LearnDash progress updates), that extra round-trip accumulates.
2. Persistence across restarts. Redis with appendonly yes and save directives retains the cache across daemon restarts. A Memcached restart empties the cache cold. On a shared managed host where the cache daemon may restart during maintenance windows, this matters for p95 tail latency.
3. Data structure support. The Redis Object Cache plugin uses Redis hashes to store cache groups, enabling HGETALL for bulk reads. Memcached stores each key individually, so bulk retrieval requires multiple round-trips.
Managed Host Support Matrix
Not every managed WordPress host lets you choose your object cache backend. Some provision Redis automatically; others require a paid add-on; a few still offer only Memcached.
| Host | Redis | Memcached | Notes |
|---|---|---|---|
| Kinsta | Yes (included) | No | Redis enabled per-site in MyKinsta dashboard |
| WP Engine | Yes (add-on, $) | No | Requires Object Cache Pro license on lower tiers |
| Cloudways | Yes (included) | Yes (included) | Both available; Redis default on new servers |
| Flywheel / Local | Yes (included) | No | Enabled by default on all plans |
| SiteGround | Yes (GoGeek+) | No | Enabled via Site Tools, uses Unix socket |
| Pressable | No | No | Full-page cache only; no persistent object cache |
| SpinupWP | Yes (included) | No | Redis 7 on all server configs |
If your host is not on this list, SSH in and run redis-cli ping and echo stats | nc localhost 11211 to check what is actually running before assuming.
Configuration Settings That Move the Needle
Installing the plugin is the easy part. These configuration decisions determine whether you get the p50 numbers above or something mediocre.
Redis maxmemory-policy
Default Redis installations often ship with maxmemory-policy noeviction, which means Redis will start returning errors when it runs out of memory rather than evicting old keys. For a WordPress object cache, set this to allkeys-lru:
maxmemory 256mb
maxmemory-policy allkeys-lru
This tells Redis to evict the least-recently-used keys when memory fills, which is the correct behavior for a cache. Without this, a busy WooCommerce site can fill Redis memory during a traffic spike and cause PHP errors that look like database connection failures.
Unix socket vs TCP
If Redis runs on the same server as PHP-FPM, use a Unix socket instead of TCP. On Site B, switching from 127.0.0.1:6379 to /var/run/redis/redis.sock reduced p50 TTFB by an additional 8 ms. Configure it in wp-config.php:
define( 'WP_REDIS_SCHEME', 'unix' );
define( 'WP_REDIS_PATH', '/var/run/redis/redis.sock' );
The Redis Object Cache plugin reads these constants automatically.
Selective cache group exclusions
Not every cache group benefits from persistence. The session group, for example, stores transient authentication data that should not outlive a request context in some configurations. The counts group (used by WooCommerce for product counts) updates frequently and may cause stale reads if cached too aggressively.
In wp-config.php:
define( 'WP_REDIS_IGNORED_GROUPS', ['session', 'counts', 'wc_session_id'] );
Test with and without these exclusions. On Site B, excluding wc_session_id eliminated a class of stale cart data bugs that appeared under concurrent load.
Memcached: set a realistic item size limit
Memcached's default item_size_max is 1 MB. WordPress serializes some cache values (term meta arrays, large option sets) that can exceed this. When a value exceeds the limit, the write silently fails and WordPress falls back to a database query — with no error log entry. Set -I 2m in your Memcached startup flags if you see cache miss rates higher than expected on a site with complex taxonomies.
Do This First
Before choosing between Redis and Memcached, verify that your site is actually constrained by database query time rather than something else. The fastest way:
- Install Query Monitor (plugin, free).
- Load a representative page while logged out.
- Check the "Queries" panel. If total query time is under 50 ms, a persistent object cache will help but is not your primary bottleneck — look at full-page caching or this guide on Core Web Vitals first.
- If total query time is above 150 ms, a persistent object cache should be your first move.
Once you have confirmed the bottleneck, the decision tree is straightforward:
- Simple blog or portfolio, low write volume → either backend works; use whatever your host provisions.
- WooCommerce, BuddyPress, LearnDash, or any high-write workload → Redis, with
allkeys-lruand Unix socket if on the same server. - Managed host with no object cache support → consider switching hosts before adding more plugins; no plugin can compensate for missing infrastructure.
Persistent Object Cache and Full-Page Cache: How They Stack
A common misconception is that full-page caching (serving a static HTML response) makes the object cache irrelevant. It does not, for two reasons.
First, full-page cache bypasses apply to logged-in users, cart pages, and checkout pages on WooCommerce sites. Those requests still hit PHP and the database. The object cache serves exactly those uncacheable requests.
Second, the object cache reduces the cost of cache miss rebuilds. When a full-page cache entry expires, WordPress regenerates the page. If the object cache is warm, that regeneration takes 60–80 ms. If the object cache is cold, it can take 400–600 ms. Under traffic spikes where many cache entries expire simultaneously (the "thundering herd" problem), this difference determines whether your site stays up.
The recommended stack for a high-traffic WordPress site: full-page cache (nginx FastCGI cache or a plugin like WP Rocket) on top of a persistent Redis object cache. Each layer handles different request types.
Conclusion
WordPress object cache is not a setting to toggle and forget. The backend choice (Redis vs Memcached), the eviction policy, the connection method, and the excluded cache groups all affect how much TTFB you actually recover. On low-query sites, the difference between backends is negligible. On WooCommerce and membership sites, Redis's group invalidation and data structure support produced p50 TTFB 27–46 ms lower than Memcached in these tests.
Measure your query time first with Query Monitor. If it is above 150 ms per page, enable Redis with allkeys-lru, switch to a Unix socket, and exclude session groups. That sequence alone should reproduce results close to the 61 ms p50 TTFB seen on Site B — without changing your theme, your host, or your content.