Skip to content
Ecom

Object Caching in WooCommerce: Redis vs Memcached vs Nothing

Benchmarks from two identical WooCommerce stores show where Redis actually helps, where Memcached holds up, and when the default advice to install Redis is wrong.

By WitsCode9 min read

Most WooCommerce performance advice begins and ends with a single sentence. Install Redis. Enable the object cache plugin. Move on. That guidance is correct often enough that it survives as received wisdom, but it hides three truths that every store operator eventually bumps into. Redis sometimes makes small stores slower. Memcached is not equivalent to Redis once you have more than one application server. And the place where a persistent object cache earns its keep is almost never the place your page speed tool points at.

We ran a controlled comparison on two mirrored WooCommerce environments after a client asked us why their Redis rollout barely moved their homepage TTFB. The answer turned out to be more useful than the benchmark numbers, and it reframes how we recommend caching layers during a WitsCode audit.

How WordPress Object Caching Actually Works

WordPress ships with a class called WP_Object_Cache that behaves as an in-memory key value store for the duration of a single PHP request. Without any plugin, the cache is populated, read, and destroyed inside one page load. Nothing persists. The next request starts from zero and hits MySQL for every option, user, post, and term lookup.

A persistent object cache changes that contract. Dropping a file named object-cache.php into wp-content rewires the default class to talk to a long-lived memory store, usually Redis, Memcached, or APCu. Now the cache survives between requests. The second visitor to your product page reads the serialized result from memory instead of reconstructing it from the database.

Two categories of data flow through this system on a WooCommerce store. The first is WordPress core object groups, the big one being alloptions, which holds every autoloaded row from wp_options. The second is transients, WooCommerce's chosen mechanism for shipping rates, tax tables, product category counts, extension license checks, and a long tail of cached computations. Without a persistent backend, transients write to wp_options. With a persistent backend, they vanish from the database entirely. That distinction is where the real savings live, and we will come back to it.

Benchmark: Two Identical Stores, Three Configurations

We cloned a production store onto two Cloudways Vultr 2GB nodes running PHP 8.2, MariaDB 10.6, and Nginx. Storefront theme, 1,200 products, 18,000 historical orders, the full WooCommerce 8.x stack. We ran k6 at 50 virtual users for five minutes hitting a realistic mix of product pages, cart fragments, and checkout submissions.

Uncached, the baseline store returned a product page with a median TTFB of 780 milliseconds and a p95 of 1,420 milliseconds. The cart fragment AJAX call sat at 410 milliseconds. The admin order list, logged in as a store manager, took 4.8 seconds to render. MySQL counted 187 queries for a single cart page view.

Adding Memcached through the W3 Total Cache drop-in brought the product page down to 520 milliseconds median with a p95 of 980. Cart fragment AJAX dropped to 260 milliseconds. Admin order list fell to 2.1 seconds. Queries per cart page collapsed to 42.

Switching to Redis using the free Redis Object Cache plugin by Till Krüss, connected over a Unix socket with igbinary serialization and Zstd compression, produced a product page TTFB of 485 milliseconds median and 920 at p95. Cart fragment 230 milliseconds. Admin order list 1.4 seconds. Queries per cart page 38.

The differences between Memcached and Redis on the frontend are real but modest, roughly 35 milliseconds at the median. The admin difference is larger in absolute terms. The interesting result came when we reconfigured the same Redis instance to listen on TCP loopback instead of a Unix socket. Product page TTFB climbed back to 560 milliseconds, slower than Memcached. The cache backend had not changed. The transport had. Many managed hosts default to TCP on 127.0.0.1:6379 and leave the socket option on the table. If you have deployed Redis and seen disappointing numbers, check this before you blame the software.

When Redis Actually Hurts

On shared hosting with fewer than roughly 500 products and fewer than 50 orders per day, a Redis rollout can make pages slower. The mechanism is simple. MySQL on a small store with a properly sized InnoDB buffer pool already serves hot rows from memory in under a millisecond. Redis over TCP adds serialization overhead on write, deserialization overhead on read, and a syscall per operation. A page making 400 cache gets pays 200 milliseconds in round trips before any logic runs. The MySQL path it replaced might have cost 150.

We have seen this on client audits more than once. Store owner reads a tutorial, installs Redis, watches their TTFB rise by 12 milliseconds, assumes the problem is elsewhere, and spends the next month chasing image optimization. The object cache was the regression.

The PHP version matters here too. On PHP 7.4 with no opcache tuning, Redis almost always wins. On PHP 8.2 with opcache preloading and JIT enabled, the PHP runtime is fast enough that small cache operations register as measurable overhead. If you are benchmarking and seeing Redis underperform, try these three changes before you conclude anything. Switch to Unix socket. Enable igbinary. Turn on compression only if your cached values average over 1KB.

The Admin Page Story Nobody Tells

Frontend performance is where teams measure, because PageSpeed Insights points a camera at the homepage. But WooCommerce stores do not make money from homepages. They make money from checkout, from the admin dashboard where staff process refunds, from the REST API that feeds mobile apps, from the AJAX endpoints that handle add-to-cart.

All of those paths bypass your page cache. Nginx FastCGI cache and Cloudflare happily serve cached HTML to anonymous visitors, but a logged-in admin viewing the orders screen runs every query, every hook, every transient fetch from scratch on each page load. That is where the dramatic numbers live. The 4.8 second admin order list collapsing to 1.4 seconds is what store staff feel during a busy Monday. Your frontend TTFB chart will not show this. Your support inbox will.

The reason is transients. WooCommerce leans on them heavily. Without persistent object caching, every transient write is an INSERT or UPDATE on wp_options, and every read is a SELECT against an autoload-polluted table. We audit stores where wp_options has ballooned past 80MB with 40,000 rows of orphaned transients that WordPress's own garbage collection struggles to clean up. The autoload column becomes a liability on every single request, cached or not, because it runs before the page cache decision happens in many stacks. Installing a persistent object cache moves those transients out of MySQL entirely, and the wp_options bloat stops growing. The admin speedup is the visible effect. The database health is the real prize.

The Memcached Multi-Server Gotcha

On a single application server, Memcached and Redis perform similarly for WooCommerce workloads. The gap opens when you scale horizontally. Two or more PHP nodes sharing a cache layer is where Memcached's architecture starts to leak.

Memcached distributes keys across nodes using consistent hashing. Add a node, roughly 1/N of your keys move addresses and miss until repopulated. Lose a node, same thing. Nothing catastrophic, just a cold window. The actual problem is flushing. WordPress's wp_cache_flush call is meant to invalidate the cache, and several popular Memcached drop-ins flush only the server holding the current connection. The other nodes keep serving stale data until natural eviction cycles them out. We have debugged prices that would not update on the catalog for twenty minutes after an import because of this. The fix is either a drop-in that explicitly iterates all configured servers on flush, or moving to Redis, where a single primary serves all application nodes and flushing is authoritative.

Memcached also has no persistence, no pub/sub, no Lua scripting, and no data types beyond strings. Extensions that want atomic list or hash operations, rate limiters, queues, or lock primitives cannot use it. Redis can. If the store's roadmap includes anything beyond basic object caching, Memcached becomes a ceiling.

Object Cache Pro and the Licensing Math

The free Redis Object Cache plugin covers the majority of stores we see. Object Cache Pro, written by the same author, is rebuilt from scratch and adds genuinely useful features. The marquee one is Relay, a PHP extension that holds a shared-memory L1 cache in front of the Redis L2. The result is that hot keys never leave the PHP worker's address space, and Redis is only consulted for misses or writes. On stores doing four-figure requests per minute with large cache working sets, this changes the performance envelope. Admin flush semantics also improve, and the WP-CLI diagnostic tools are worth money on their own during incident response.

The cost is real. Object Cache Pro is bundled free on Cloudways, Kinsta, and Rocket.net at certain plans, but outside those, direct licensing starts around 95 dollars per month and climbs. For a store doing under 5,000 orders a month, the free plugin plus a properly tuned MySQL buffer pool plus a Unix socket Redis connection will deliver 90 percent of the benefit. For stores doing 50,000 plus orders a month with multiple warehouse locations and complex tax rules, the Relay layer pays back the license inside a month in reduced compute. The middle ground is where the honest recommendation depends on the full picture, which is why we run the numbers in every audit rather than default to one answer.

MySQL Is Not a Caching Layer You Should Ignore

A sidebar worth internalizing. MySQL 8.0 removed the query cache entirely. Before 8.0, the query cache helped but invalidated on any write to the underlying table, and WooCommerce stores write constantly to orders and stock tables. The caching that does matter at the database layer is the InnoDB buffer pool. Sized to roughly 60 to 70 percent of available RAM, it keeps hot indexes and rows resident in memory. On read-dominant workloads it is astonishingly effective.

A well-tuned MySQL instance reduces the delta between cached and uncached reads, which is another reason tiny stores see smaller gains from Redis. On write-burst workloads like a flash sale, the buffer pool thrashes, and the application-level object cache becomes critical because it absorbs the read traffic MySQL can no longer serve from memory.

If you are evaluating object cache ROI and your MySQL has default my.cnf values with a 128MB buffer pool on an 8GB server, fix that first. Then measure.

A Practical Decision Framework

For a brochure-grade WooCommerce site under 100 products with light traffic, skip the persistent object cache. A page cache from WP Rocket or FastCGI plus Cloudflare in front handles the public pages, and the admin load is too light to matter. You are adding operational complexity for a 15 millisecond gain that will get lost in network jitter.

For a growing store where staff complain about the admin feeling sluggish, install the free Redis Object Cache plugin, connect over a Unix socket, enable igbinary, and leave compression off unless your cached values are large. The admin speedup is immediate and the plugin is stable.

For a multi-server deployment or a store approaching five-digit daily order counts, centralize on Redis with persistence enabled and a sentinel or replica for failover. Evaluate Object Cache Pro if your host bundles it or if your traffic justifies the license. Avoid Memcached in multi-node deployments unless you have verified the flush semantics of your specific drop-in.

For any store above 50,000 orders per month, the caching question is downstream of an architecture question. You are now in a region where dedicated Redis clusters, read replicas, queue-based checkout, and edge-computed cart totals start to matter more than which object cache plugin you chose.

Where WitsCode Comes In

Across the 250-plus WooCommerce deployments we have audited, the pattern is consistent. Teams either have no object cache and are leaving easy wins on the table, or they have Redis installed with default settings and assume the job is done. Both situations cost money, one in lost performance, the other in wasted infrastructure spend.

A WitsCode caching audit looks at the whole stack. We measure TTFB on both cached and uncached paths. We profile the admin experience your staff actually lives in. We inspect wp_options for transient bloat and autoload weight. We validate your Redis transport, serializer, and eviction policy. We compare the cost of Object Cache Pro against the throughput gain we can measure, not guess at. Then we tell you which of the three columns in this article, Redis, Memcached, or nothing, your store belongs in, and we configure it correctly.

If your Redis rollout did not move the numbers you expected, or if you have never installed one and want to know whether it is worth the ticket, that is exactly the conversation to start with a WitsCode WooCommerce caching audit. We will right-size your cache layer so you stop paying for performance you are not getting.

Get weekly field notes.

Practical writing on shipping products, straight to your inbox. No spam.

Need help with this?

Shopify Development

We design and build web apps, MVPs, and SaaS products. Talk to us about what you are working on.

Talk to us

Want to discuss ecom for your business?

Start a project and we'll talk through where you are, what's working, and the highest-leverage moves for the next 90 days.