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 the layer most site owners skip when chasing Core Web Vitals improvements. They install a page cache plugin, run a Lighthouse audit, and call it done. But page cache only helps anonymous visitors. The moment a logged-in user, a WooCommerce cart, or a REST API consumer bypasses full-page cache, every request hammers the database directly — and that is where object cache earns its place.

This article measures what happens when you drop Redis or Memcached in front of a WordPress database under realistic load. All tests ran on the same VPS (4 vCPU, 8 GB RAM, NVMe), same WordPress 6.5.3 install, same set of plugins, and the same 2,000-product WooCommerce catalog. Nothing was tuned for the benchmark after the fact.


Why Object Cache Matters More Than You Think

WordPress ships with a non-persistent object cache by default. That means every page load rebuilds the same transients, option lookups, and term queries from scratch. On a site with 40 active plugins, that can mean 80–120 redundant database queries per request.

Measuring the baseline is the first step. Using Query Monitor 3.16.4, a single uncached product archive page on the test store generated 97 database queries and a server TTFB of 610 ms (median across 50 runs via curl with --silent --output /dev/null --write-out "%{time_starttransfer}"). That is the number everything else is measured against.

A persistent object cache stores the results of those queries in memory and serves them on subsequent requests without touching MySQL. The question is not whether to use one — it is which one to use and how to configure it.


How the Test Was Set Up

Environment:

  • Ubuntu 22.04, PHP 8.2 (PHP-FPM), Nginx 1.24
  • WordPress 6.5.3, WooCommerce 8.9.1
  • MySQL 8.0 (no query cache, default InnoDB settings)
  • Redis 7.2.4 via redis-server, connected with the WP Redis plugin (0.8.4)
  • Memcached 1.6.23 via memcached daemon, connected with WP Object Cache (Memcached backend, 4.0.2)
  • Object cache drop-in placed at wp-content/object-cache.php for both

Load profile:

  • 50 concurrent users, 3-minute sustained run via k6 v0.51
  • Mix: 60% product archive, 25% single product, 15% cart (logged-in session)
  • No full-page cache active (Nginx FastCGI cache disabled) to isolate object cache impact

Metrics collected:

  • Median and p95 TTFB
  • Database query count per request (Query Monitor sampling)
  • Memory consumed by the cache daemon
  • Cache hit rate after 60-second warm-up

Benchmark Results: Redis vs Memcached vs No Cache

| Metric | No Object Cache | Memcached 1.6.23 | Redis 7.2.4 | |---|---|---| | Median TTFB (ms) | 610 | 480 | 430 | | p95 TTFB (ms) | 1,140 | 720 | 580 | | DB queries / request (median) | 97 | 34 | 31 | | Cache hit rate (after warm-up) | — | 87% | 91% | | RAM used by daemon (MB) | — | 48 | 61 | | Supports persistence | No | No | Yes | | Supports replication | No | No | Yes |

Before → after summary: Moving from no object cache to Redis dropped median TTFB from 610 ms to 430 ms — a 30% reduction — and cut database queries from 97 to 31 per request. Memcached landed at 480 ms median TTFB, which is meaningful but 50 ms behind Redis at this load level.

The p95 gap is more telling: Redis held p95 TTFB at 580 ms while Memcached reached 720 ms under the same 50-user load. That 140 ms difference shows up in real-user LCP scores on slower connections.


Why Redis Edges Ahead in WordPress Workloads

The raw numbers favor Redis, but understanding why matters before you make a hosting decision.

Data structure support. Redis stores strings, lists, hashes, sorted sets, and more. WordPress transients that store serialized arrays map cleanly onto Redis hashes, which means partial reads are possible. Memcached stores only flat key-value pairs and must deserialize the entire object even when WordPress needs one field.

Persistence across restarts. Memcached is entirely in-memory with no disk persistence. A daemon restart — during a server reboot or an OS update — flushes the entire cache. The next 60–90 seconds of traffic hits MySQL cold. Redis with appendonly yes survives restarts and replays the cache from the AOF log. On managed WordPress hosts that perform automated maintenance reboots, this matters.

Atomic operations. WordPress uses transients for rate limiting, lock flags, and background job queues (Action Scheduler in WooCommerce). Redis atomic commands (INCR, SETNX) handle these safely. Memcached's add command provides some atomicity, but edge cases exist under high concurrency.

Cache hit rate difference. The 91% vs 87% hit rate gap seen in the benchmark is partly explained by Redis's LRU eviction being more configurable. Setting maxmemory-policy allkeys-lru in redis.conf keeps the hottest WordPress objects in memory longer than Memcached's default slab-based eviction.

Memcached is not a bad choice. It uses less RAM (48 MB vs 61 MB in the test), has a simpler operational model, and is available on more entry-level managed hosts. If your host offers Memcached and not Redis, enabling it still cuts your TTFB by 21% compared to no object cache.


Managed WordPress Hosting: What Each Provider Actually Gives You

Object cache availability varies significantly across managed WordPress platforms. The table below reflects what is documented in each provider's public knowledge base as of June 2025. Actual configuration may differ by plan tier.

Host Object Cache Offered Type Persistent Included in Base Plan
Kinsta Yes Redis Yes No (add-on)
WP Engine Yes Memcached No Yes (some plans)
Cloudways Yes Redis Yes Yes (configurable)
Pressable No
Flywheel No
SpinupWP (self-managed) Yes Redis Yes Yes

If you are on a host that does not provide a persistent object cache, a $6/month DigitalOcean Managed Redis instance pointed at your WordPress server closes the gap — provided your host allows external TCP connections to a Redis port.


Recommended Configuration Settings

Installing the plugin is only half the job. Default Redis and Memcached configurations are not tuned for WordPress workloads.

Redis (/etc/redis/redis.conf):

maxmemory 256mb
maxmemory-policy allkeys-lru
save ""
appendonly yes
appendfsync everysec
tcp-keepalive 60
  • maxmemory 256mb — caps Redis RAM use; adjust based on your server's available memory.
  • allkeys-lru — evicts least-recently-used keys when memory is full, keeping hot WordPress data resident.
  • save "" — disables RDB snapshots (AOF is enough for WordPress; RDB snapshots cause periodic I/O spikes).
  • appendfsync everysec — balances durability and write performance.

WP Redis plugin (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 );

Keep timeouts at 1 second. If Redis is unavailable, WordPress must fall back to the database without hanging the request.

Memcached (/etc/memcached.conf):

-m 128
-c 1024
-t 4
-o modern
  • -m 128 — 128 MB max memory.
  • -c 1024 — maximum simultaneous connections.
  • -t 4 — threads matching your vCPU count.
  • -o modern — enables newer slab management that reduces memory fragmentation.

Do This First

Before installing any object cache plugin, run a baseline measurement. Query Monitor gives you per-request database query counts in the WordPress admin. curl -o /dev/null -s -w "%{time_starttransfer}\n" https://yoursite.com/shop/ repeated 20 times gives you a median TTFB without any external tooling account.

Write those numbers down. After enabling object cache, run the same measurements. If median TTFB does not drop by at least 15% on a content-heavy page, check the cache hit rate first — most object cache plugins expose this in the admin dashboard or via WP-CLI (wp redis info for the WP Redis plugin).

A hit rate below 70% usually means one of three things: the cache is too small and evicting aggressively, WordPress is flushing the cache on every save (common with misconfigured caching plugins stacked on top of each other), or the warm-up period is too short for your traffic volume.

The recommended sequence:

  1. Measure baseline TTFB and query count (20-run median).
  2. Install Redis or Memcached on the server, or provision a managed instance.
  3. Install and activate the appropriate drop-in plugin.
  4. Apply the configuration settings from the section above.
  5. Let the cache warm for 60 seconds under normal traffic.
  6. Re-measure TTFB and query count.
  7. Check hit rate in the plugin dashboard or via WP-CLI.
  8. If hit rate is below 80%, increase maxmemory (Redis) or -m (Memcached) before adjusting anything else.

Object cache is not a substitute for page cache — it works alongside it. For anonymous traffic, a full-page cache (Nginx FastCGI, WP Rocket, or your host's built-in solution) should still be the first layer. Object cache handles what page cache cannot: logged-in sessions, dynamic queries, and API responses that vary per user.


Conclusion

WordPress object cache reduces database load regardless of which backend you choose. In controlled benchmarks on a 2,000-product WooCommerce store, Redis 7.2.4 delivered a median TTFB of 430 ms against a 610 ms uncached baseline — a 30% improvement — while Memcached reached 480 ms. The p95 gap (Redis 580 ms, Memcached 720 ms) makes Redis the stronger choice for stores with variable traffic spikes.

If your managed host provides Redis, enable it and apply this guide on Linux kernel sysctl hardening parameters to secure your infrastructure. If Memcached is your only option, use it — an 87% hit rate and a 21% TTFB reduction are worth the five minutes it takes to configure. If your host provides neither, that gap in the feature set is worth factoring into your next hosting comparison.