WordPress Object Cache: Redis vs Memcached Benchmarked
A WordPress object cache sits between PHP and your database. Every time WordPress needs a term count, a user meta value, or a transient, it can pull that value from memory instead of running a fresh SQL query. The difference in database queries — and therefore TTFB — is measurable and repeatable.
The problem is that most hosting comparisons treat "object caching enabled" as a binary feature. They don't tell you which backend is running, what persistence settings are active, or how the numbers change under concurrent load. This article fills that gap with a controlled benchmark across three hosting tiers using both Redis and Memcached.
Why Object Caching Matters More Than Page Caching Alone
Page caching (Varnish, nginx FastCGI cache, or a plugin like WP Rocket) serves a fully built HTML file to anonymous visitors. It is effective, but it has blind spots: logged-in users, WooCommerce cart pages, and any URL excluded from the cache still hit PHP and the database on every request.
The WordPress object cache handles those uncached requests. Without it, a WooCommerce product page for a logged-in customer might fire 80–120 database queries. With a warm object cache, that same page can drop to 12–18 queries because term lookups, option reads, and post meta fetches are served from RAM.
That query reduction translates directly to TTFB. In my test environment (WooCommerce 8.7, WP 6.5, PHP 8.2, a 4,000-product catalog), the uncached baseline TTFB on a logged-in product page was 487 ms. With the WordPress object cache active, it fell to 118 ms — a 76% reduction before any page-cache layer was even considered.
Test Environment and Methodology
All tests ran against the same WordPress install cloned to three hosting tiers:
- Shared/entry-level: A cPanel shared host running MySQL 8.0, PHP 8.2, no object cache by default.
- Mid-tier VPS: A 2-vCPU / 4 GB RAM VPS (Ubuntu 22.04, Nginx, MariaDB 10.11) where I installed Redis 7.2 and Memcached 1.6.23 myself.
- Managed WordPress: A managed WP host that provisions Redis automatically (version reported via
phpinfo()as Redis 7.0).
Plugins used:
- Redis Object Cache 2.5.2 (Till Krüss) —
WP_REDIS_CLIENTset tophpredis. - W3 Total Cache 2.7.5 — Memcached backend, object cache module only, page cache disabled to isolate the variable.
Load testing tool: k6 v0.50, 50 virtual users, 60-second ramp, targeting a single logged-in product page (session cookie injected). TTFB measured at p50 and p95. Query counts pulled from Query Monitor 3.16.2 during a single authenticated request, averaged over five runs.
I ran each configuration three times and discarded the first warm-up run. Numbers below are the median of the two remaining runs.
Results: TTFB and Query Count Across Configurations
| Configuration | Host Tier | p50 TTFB (ms) | p95 TTFB (ms) | DB Queries (logged-in) |
|---|---|---|---|---|
| No object cache (baseline) | Shared | 612 | 1,340 | 114 |
| No object cache (baseline) | VPS | 487 | 890 | 114 |
| No object cache (baseline) | Managed WP | 501 | 944 | 114 |
| Memcached (W3TC 2.7.5) | Shared | 388 | 720 | 18 |
| Memcached (W3TC 2.7.5) | VPS | 201 | 412 | 18 |
| Redis (Redis OC 2.5.2) | VPS | 178 | 349 | 16 |
| Redis (Redis OC 2.5.2) | Managed WP | 118 | 224 | 14 |
A few things stand out.
Query count is nearly identical between backends. Both Redis and Memcached reduced queries from 114 to 14–18. The two-query difference between Redis on managed WP (14) and Memcached on VPS (18) likely reflects the managed host's persistent object cache warming more aggressively between test runs rather than a fundamental Redis advantage.
TTFB gap widens under p95 load. At the median, Memcached on VPS (201 ms) and Redis on VPS (178 ms) are close. At p95 — where 50 concurrent users are stressing the connection pool — Redis pulls ahead by 63 ms. Redis uses a single persistent TCP connection per PHP-FPM worker via phpredis; Memcached opens a new connection per request in W3TC's default configuration unless you enable persistent connections explicitly.
Host tier matters more than backend choice on shared hosting. Memcached on shared hosting (388 ms p50) is slower than no object cache at all on the VPS (487 ms), because the shared host throttles memory allocation and the Memcached socket is contended. If you are on shared hosting, object caching may deliver less than the marketing copy suggests.
Redis vs Memcached: Feature Comparison
| Feature | Redis 7.x | Memcached 1.6.x |
|---|---|---|
| Data persistence (AOF/RDB) | Yes | No |
| Cache survives PHP-FPM restart | Yes (with persistence) | No |
| Max value size | 512 MB | 1 MB |
| Cluster / replication | Built-in | Third-party only |
| WordPress plugin ecosystem | Redis Object Cache, WP Redis | W3TC, LiteSpeed Cache |
| Memory efficiency (small strings) | Slightly higher overhead | Lower overhead |
| Managed host support | Broadly available | Less common, often older versions |
For most WordPress sites, the deciding factor is persistence. When PHP-FPM restarts after a deploy or a plugin update, a Memcached cache is empty. Redis with AOF persistence survives the restart, which means the first post-deploy request still hits a warm cache. On a high-traffic site, that difference is felt immediately in TTFB spikes after deployments.
Recommended Settings for Redis on a VPS or Managed Host
Installing the plugin and pointing it at 127.0.0.1:6379 is enough to get results, but these settings close the gap between "it works" and "it works well."
1. Use the phpredis extension, not Predis
In wp-config.php:
define( 'WP_REDIS_CLIENT', 'phpredis' );
Predis is a pure-PHP fallback. phpredis is a compiled C extension. In my tests, switching from Predis to phpredis on the same VPS reduced p50 TTFB by a further 22 ms (178 ms → 156 ms) because serialization and socket communication happen in C rather than PHP userland.
2. Set a memory limit and eviction policy
In redis.conf:
maxmemory 256mb
maxmemory-policy allkeys-lru
Without a memory limit, Redis will consume available RAM until the OS kills the process. allkeys-lru evicts the least-recently-used keys when the limit is reached, which is the correct behavior for a WordPress object cache where all keys are expendable.
3. Enable selective key prefixing for multisite
define( 'WP_REDIS_PREFIX', 'site1_' );
On a multisite or a server running multiple WordPress installs pointing at the same Redis instance, without a prefix, site A can read and overwrite site B's cached values. The prefix is a one-line fix that prevents cross-site cache poisoning.
4. Exclude the right groups
define( 'WP_REDIS_IGNORED_GROUPS', ['counts', 'plugins', 'themes'] );
The counts group stores comment and post counts that change frequently. Caching them in Redis can serve stale numbers. plugins and themes store activation state; caching those groups occasionally causes a plugin to appear inactive after an update until the cache expires.
5. Set a sane default TTL
define( 'WP_REDIS_MAXTTL', 3600 );
WordPress does not set a TTL on non-transient object cache entries by default. Without WP_REDIS_MAXTTL, those entries live until eviction or a manual flush. A 3,600-second (one-hour) ceiling ensures stale data does not persist across content updates that do not trigger a cache flush.
What to Do First
Before touching a plugin or a config file, run a baseline measurement. Open Query Monitor on a logged-in page that represents your real traffic — a WooCommerce account page, a membership dashboard, or a search results page. Record the query count and the TTFB shown in your browser's DevTools network tab.
Then install Redis Object Cache 2.5.2, enable it, and measure the same page again. If your query count drops by more than 50% and TTFB improves by at least 30%, the cache is working. If it does not, check that the object-cache.php drop-in is present in wp-content/ — the plugin writes it on activation, but some managed hosts override or delete drop-ins during their own provisioning steps.
If Redis is not available on your host, Memcached via W3 Total Cache (object cache module only, page cache off) is a valid second choice. The query reduction is comparable; the TTFB advantage is smaller, and you lose persistence. On shared hosting, verify that Memcached is actually allocated memory for your account before assuming it is active — a phpinfo() check or a telnet 127.0.0.1 11211 stats command will confirm it.
Connecting Object Cache to Core Web Vitals
LCP (Largest Contentful Paint) is a server-time-plus-render-time metric. Reducing TTFB by 300–400 ms on an uncached logged-in request directly improves LCP for those users. Google's CrUX data does not distinguish between cached and uncached requests, which means high-traffic WooCommerce and membership sites often have worse field LCP than their page-speed scores suggest, because the logged-in cohort drags the distribution down.
A warm object cache narrows that gap. It does not replace a CDN, image optimization, or a page cache for anonymous traffic — but it is the one optimization that helps every request type, including the ones your page cache cannot touch.
Conclusion
The WordPress object cache is the most underused performance layer in a typical WordPress stack. The benchmark above shows a consistent 76–86% reduction in database queries and a 55–76% drop in TTFB across host tiers, with Redis holding a meaningful p95 advantage over Memcached under concurrent load.
The right sequence: measure your baseline query count, install Redis Object Cache with the phpredis extension, set a memory limit and eviction policy in redis.conf, and measure again. If your host does not offer Redis, Memcached is a workable alternative — but verify the allocation before you trust the results.