DEV Community

Hamza Ahmad Aslam
Hamza Ahmad Aslam

Posted on Originally published at hamzaahmadaslam.com

WordPress Redis object cache: setup and measurement

Originally published at hamzaahmadaslam.com.

How this article was made: drafted with AI assistance from a researched brief, then checked against primary documentation before publishing.

Short answer: A WordPress Redis object cache keeps WordPress object-cache data available across requests, so PHP can reuse cached query results and other objects instead of rebuilding them each time. It helps most on requests that still execute WordPress, such as logged-in pages, wp-admin, WooCommerce flows, and uncached front-end requests.

What a WordPress Redis object cache changes

WordPress includes WP_Object_Cache, but the default implementation keeps cached objects only for the current request. WordPress documents that behavior in the WP_Object_Cache reference. A persistent object cache replaces that request-only storage with a backend that survives between requests.

WordPress loads a persistent cache through wp-content/object-cache.php. The Redis Object Cache plugin installs that object-cache.php drop-in and routes WordPress wp_cache_*() calls to Redis.

This is separate from full-page caching. A page cache can return stored HTML before WordPress runs. Redis helps after PHP and WordPress are involved, which is why it is most useful for admin screens, authenticated traffic, API requests, cart and checkout activity, and pages that miss the page cache.

A cache hit can avoid database work or repeated computation. A miss still has to build the value, then Redis can store it for later requests.

How to set up the Redis Object Cache plugin

The current Redis Object Cache project documentation lists these WP-CLI commands:

wp redis enable
wp redis status
wp redis disable
wp redis update-dropin
Enter fullscreen mode Exit fullscreen mode

wp redis enable enables the persistent object cache. wp redis status shows connection and drop-in diagnostics. wp redis disable disables it, and wp redis update-dropin refreshes the installed drop-in.

Run the status command after enabling Redis:

wp redis enable
wp redis status
Enter fullscreen mode Exit fullscreen mode

Check that the plugin reports a connected Redis backend and a valid object-cache.php drop-in. If status reports that Redis is not connected, fix the Redis service, hostname, port, authentication, or socket path before measuring performance.

Configure the connection and key namespace

The plugin currently documents 127.0.0.1 as the default host, 6379 as the default port, database 0 as the default database, and one second for both connection and read/write timeouts.

A basic wp-config.php setup can look like this:

define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_DATABASE', 0 );

define( 'WP_REDIS_PREFIX', 'example-prod:' );

define( 'WP_REDIS_TIMEOUT', 1 );
define( 'WP_REDIS_READ_TIMEOUT', 1 );

define( 'WP_REDIS_MAXTTL', 0 );
Enter fullscreen mode Exit fullscreen mode

WP_REDIS_PREFIX is the current plugin setting for separating key namespaces. WP_REDIS_MAXTTL has a documented default of 0, which means the plugin does not impose a maximum TTL.

The plugin documentation now marks WP_CACHE_KEY_SALT as deprecated and says WP_REDIS_PREFIX replaces it. Do not add a new WP_CACHE_KEY_SALT for this plugin. If a legacy installation already uses one, plan the namespace change carefully because changing prefixes makes existing Redis keys unreachable to that site.

Isolate shared Redis and multisite installations

Every independent WordPress installation sharing a Redis service needs its own key namespace. Use a unique WP_REDIS_PREFIX for each installation. The plugin also supports selecting a Redis database with WP_REDIS_DATABASE where the Redis topology supports database selection.

On WordPress multisite, one network still needs a namespace that does not collide with another WordPress installation. WordPress object-cache APIs also distinguish global groups from site-specific groups, so do not try to create per-site prefixes manually inside plugin code.

How to measure cache hits, misses, and memory

Do not judge Redis only by whether wp redis status says "connected." Measure whether requests are reusing cached objects and whether Redis is under memory pressure.

Redis exposes the required counters through the INFO command.

Run:

redis-cli INFO stats
redis-cli INFO memory
Enter fullscreen mode Exit fullscreen mode

If Redis is on another host:

redis-cli -h redis.internal -p 6379 INFO stats
redis-cli -h redis.internal -p 6379 INFO memory
Enter fullscreen mode Exit fullscreen mode

For authenticated environments, use the authentication method required by that Redis deployment rather than placing secrets directly in shell history.

Example output from INFO stats might look like this. These values are illustrative:

keyspace_hits:1250400
keyspace_misses:246000
evicted_keys:3100
expired_keys:18422
Enter fullscreen mode Exit fullscreen mode

Compute the cache hit ratio as:

hit ratio = keyspace_hits / (keyspace_hits + keyspace_misses) * 100

hit ratio = 1250400 / (1250400 + 246000) * 100
hit ratio = 83.6%
Enter fullscreen mode Exit fullscreen mode

That percentage is only the result of this example. It is not a universal target. Compare the ratio before and after configuration changes, and compare it with page generation time, database query work, and Redis latency.

Example output from INFO memory might look like this:

used_memory:268435456
used_memory_human:256.00M
maxmemory:536870912
maxmemory_human:512.00M
maxmemory_policy:allkeys-lru
Enter fullscreen mode Exit fullscreen mode

used_memory shows Redis-managed memory in use. maxmemory is the configured memory ceiling. maxmemory_policy reports the active eviction policy.

How Redis evictions affect WordPress

For a Redis instance used only as a cache, set a deliberate memory ceiling and an eviction policy that can remove cache entries when the limit is reached. Redis documents allkeys-lru as a cache configuration example in its Redis configuration guide.

A Redis configuration can include:

maxmemory 512mb
maxmemory-policy allkeys-lru
Enter fullscreen mode Exit fullscreen mode

The memory size here is an example configuration value, not a recommendation for every site. Size the limit from the workload and available memory.

allkeys-lru makes all keys eligible for approximate least-recently-used eviction. That is a reasonable fit when the Redis instance contains disposable cache data only. Do not apply it blindly to a Redis server that also stores data that must never be evicted.

Watch evicted_keys in INFO stats. A rising value means Redis is removing keys because it reached the maxmemory limit. Occasional eviction can be normal for a bounded cache, but sustained growth can lower reuse and force WordPress to rebuild objects repeatedly.

If used_memory stays close to maxmemory, evicted_keys keeps climbing, and misses rise, the cache may be too small for the active working set.

How non-persistent groups differ from plugin ignored groups

WordPress provides wp_cache_add_non_persistent_groups() so code can mark groups that should not survive between requests. Core currently registers groups such as counts, plugins, and theme_json as non-persistent.

Plugin or theme code can register its own request-only group:

wp_cache_add_non_persistent_groups(
    array(
        'my_request_only_data',
    )
);
Enter fullscreen mode Exit fullscreen mode

Use this only when the data is safe for the current request but should not be reused by later requests. Examples include values that depend on request-specific state that the cache key does not fully represent.

WP_REDIS_IGNORED_GROUPS is different. It is a Redis Object Cache plugin configuration constant. The plugin documents it as a list of groups that should not be cached between requests in Redis, with an empty array as the default.

The two mechanisms can produce similar persistence behavior with this plugin, but they are not the same API. wp_cache_add_non_persistent_groups() is the WordPress cache interface. WP_REDIS_IGNORED_GROUPS is plugin-specific configuration. Do not copy core groups into the plugin constant unless a specific compatibility case requires it.

How to tell when Redis is making WordPress slower

Redis can add time instead of removing it when each lookup costs more than the work it avoids.

A remote Redis server adds network round trips to object-cache calls. Measure that path from the WordPress host:

redis-cli -h redis.internal -p 6379 --latency
Enter fullscreen mode Exit fullscreen mode

Example output might look like this:

min: 1, max: 4, avg: 1.62 (420 samples)
Enter fullscreen mode Exit fullscreen mode

Redis documents --latency as repeated PING timing in milliseconds. This is not PHP application timing, but it helps reveal network delay between the WordPress host and Redis.

A low hit ratio is another warning. If many cache lookups miss, WordPress pays for the Redis request and still performs the database or computation work.

Large serialized values can also hurt. They cost transfer time plus PHP serialization or unserialization work. The alloptions object deserves special attention because WordPress loads and caches autoloaded options together. A very large autoloaded set can turn one cache lookup into a large payload on many requests. An autoloaded option rewritten on every request also replaces that cached copy each time, and the option-churn plugin finds such options by counting writes across many requests and naming the plugin, theme or core function that made them.

Frequent full cache flushes erase reuse. If hits fall sharply after deploys, imports, scheduled jobs, or plugin actions, look for code that flushes the entire object cache instead of invalidating only affected data.

What happens when Redis is unavailable

The Redis Object Cache 2.3.0 changelog says, "Throw errors when connection error occurs." The current documentation does not provide a transparent fallback that silently switches to the default WordPress cache after Redis fails.

Current Redis Object Cache documentation lists WP_REDIS_DISABLED as an emergency switch that bypasses the object cache without deleting the drop-in:

define( 'WP_REDIS_DISABLED', true );
Enter fullscreen mode Exit fullscreen mode

The same documentation describes WP_REDIS_GRACEFUL as a setting that "Prevents exceptions from being thrown, but will cause data corruption." Do not use it as an automatic failover setting.

The practical failure plan is to keep Redis available where the site depends on it, monitor connection errors, and have a controlled way to set WP_REDIS_DISABLED during an outage. That lets WordPress run without the persistent Redis backend while the service is repaired.

Test this path before production incidents. Disable Redis in a staging environment, confirm WordPress still boots, then verify the application under the non-persistent object cache behavior.

What Redis changes for WooCommerce

WooCommerce's WC_Session_Handler has stored sessions in a custom database table since WooCommerce 2.5. The current WooCommerce WC_Session_Handler source uses the WordPress table prefix plus woocommerce_sessions.

The session handler also caches each session row through the WordPress object-cache API under its session cache group. It reads the cached value with wp_cache_get() before querying the table, and uses wp_cache_add() or wp_cache_set() when caching session data.

With a persistent Redis object cache active, an active WooCommerce session can therefore be read from Redis while the custom session table remains the source of truth. Redis does not replace WooCommerce's session table.

Redis also helps a store because WooCommerce requests read many WordPress objects outside session storage. Products, metadata, options, users, terms, and plugin data can all involve object-cache lookups.

Cart, checkout, account, and admin requests often bypass full-page caching, so persistent object caching can matter more there than on a fully cached brochure page. Measure those request types separately instead of relying on homepage results.

What to do next

After Redis is connected, compare time to first byte on uncached and authenticated requests. If wp-admin remains slow, follow the slow WordPress admin guide.

If alloptions is large, measure ownership and autoload size with the WordPress autoloaded options guide. For site-wide profiling and remediation, use the WordPress performance optimization service.

Top comments (0)