Skip to content

Redis Object Cache

A persistent WordPress object cache backed by Redis via the PhpRedis extension. New in v2.0.0. Replaces wp-content/object-cache.php with a Redis-backed WP_Object_Cache that's a drop-in superset of Till Krüss's redis-cache and Pantheon's wp-redis — you can swap in without editing wp-config.php.

What it does

Persistent storage for the WordPress object cache, so values written by wp_cache_set() survive across PHP requests. Without a drop-in like this one, WordPress's default object cache lives in PHP memory for a single request and is discarded when the request ends — every page rebuilds everything from scratch.

Requirements

  • The PhpRedis PHP extension (a C extension, much faster than pure-PHP alternatives).
  • A reachable Redis server.

If PhpRedis isn't installed, the Object Cache tab in wp-admin tells you so and the plugin doesn't try to install the drop-in.

Common installation paths:

  • Debian/Ubuntu: apt install php-redis
  • RHEL/Rocky/Alma: dnf install php-pecl-redis6 (via remi-modular)
  • macOS (Homebrew PHP): pecl install redis

Installation

  1. Set the Redis connection constants in wp-config.php (only WP_REDIS_HOST is strictly required for a local Redis on the default port):
define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_DATABASE', 0 );
define( 'WP_REDIS_PREFIX', 'mysite_' );
  1. In wp-admin, open Cacheability Pro → Object Cache. Confirm the connection shows green (sub-millisecond is normal on a local Redis).

  2. Click Install drop-in. The drop-in is copied to wp-content/object-cache.php. The tab will reload and show "Installed (ours, v1)".

  3. Browse a few pages, then come back. The connection panel updates; the drop-in is now serving cache reads.

To remove it, click Remove drop-in. We never touch a foreign drop-in installed by another plugin.

Configuration constants

All read from wp-config.php. None are required for a local Redis on default port.

Constant Default Purpose
WP_REDIS_HOST 127.0.0.1 Redis hostname or IP.
WP_REDIS_PORT 6379 Redis port.
WP_REDIS_SOCKET (none) Unix socket path. Used instead of host/port when set.
WP_REDIS_DATABASE 0 Redis DB number to SELECT.
WP_REDIS_PREFIX (none) Cluster-wide key prefix. Use {blog_id} token for multisite to keep sites isolated, e.g. site_{blog_id}_.
WP_REDIS_PASSWORD (none) Redis AUTH password.
WP_REDIS_USERNAME (none) Redis 6 ACL username (paired with PASSWORD).
WP_REDIS_TIMEOUT 1.0 Connect timeout in seconds.
WP_REDIS_READ_TIMEOUT 1.0 Read timeout in seconds.
WP_REDIS_URL (none) One-line config: redis://[user:pass@]host:port[/db][?prefix=foo:]. Decomposes into the individual constants above.
WP_REDIS_TLS false When true, connects over TLS. The host is prefixed with tls:// automatically.
WP_REDIS_TLS_CA (none) Path to CA cert for TLS verification.
WP_REDIS_TLS_VERIFY_PEER true Verify the Redis server's TLS cert.
WP_REDIS_DISABLED false Master kill switch. When true, the drop-in returns early and WordPress falls back to its default in-memory cache. Set this if Redis is misbehaving and you need an instant rollback.
WP_REDIS_PERSISTENT false Use pconnect() instead of connect(). Faster but can leak handles on PHP fatals.
WP_REDIS_MAXTTL 0 (no cap) Maximum TTL we'll accept; longer expirations get capped. The cap counter is surfaced in the admin tab so you know when it fires.
WP_REDIS_GRACEFUL true Swallow RedisException silently. Disable for development if you want errors to surface.
WP_REDIS_GLOBAL_GROUPS (none) Array of group names treated as global across multisite (extends our defaults).
WP_REDIS_IGNORED_GROUPS (none) Array of group names that stay in-process and never round-trip Redis (extends our defaults).
WP_REDIS_SCAN_COUNT 1000 Batch size for SCAN operations during flush.
WP_REDIS_ALLOWED_CLASSES (built-in safelist) Override the object-injection safelist. Array of allowed class names, or true to allow all (debug only).

Storage format

The drop-in writes every value with a 2-byte type prefix so reads dispatch correctly without trial-and-error unserializing:

Prefix Meaning Example
s: raw string scalar s:hello world
i: integer i:42
b: boolean b:1
f: float f:3.14
p: PHP serialize() payload p:a:1:{s:1:"a";i:1;}

This is custom — other drop-ins won't read it. The key namespace is ours alone, so there's no collision. If you inspect Redis with redis-cli you'll see these prefixes.

Migration from redis-cache (Till Krüss)

  1. Run wp redis disable to remove that plugin's drop-in cleanly via WP_Filesystem.
  2. Deactivate the "Redis Object Cache" plugin in Plugins.
  3. Confirm wp-content/object-cache.php is gone.
  4. In Cacheability Pro → Object Cache, click Install drop-in.

If WP-CLI isn't available, deactivate the plugin and delete the file by hand via SFTP / your file manager, then install ours.

Migration from wp-redis (Pantheon)

  1. Deactivate the "WP Redis" plugin in Plugins.
  2. Delete (or unlink) wp-content/object-cache.php.
  3. In Cacheability Pro → Object Cache, click Install drop-in.

Note: Pantheon's plugin doesn't ship a CLI uninstaller, so the manual file deletion is required.

Comparison with redis-cache and wp-redis

What we do differently Till Krüss redis-cache Pantheon wp-redis
One round-trip MGET for wp_cache_get_multiple Per-key timing + serialize loop Hash-fallback loop
Scalars stored without serialize() (raw i:42) serialize("42")"i:42;" Always serialize non-int
wp_cache_flush scoped to site only, SCAN + UNLINK Hardcoded SCAN count, global flush risk Blocking FLUSHDB
Object-injection-safe unserialize with class safelist (paid-tier feature) Raw unserialize
Re-serializes a string that looks serialized Yes (bug) OK
Per-group wp_cache_delete always hits Redis OK Footgun: WP_REDIS_USE_CACHE_GROUPS=false by default
TLS + Redis 6 ACL out of the box Paid-tier feature None
WP_REDIS_DISABLED honored Yes No
One-click installer in wp-admin Yes No (manual symlink)
Detects and warns about competing drop-ins Limited None
Multisite shared-prefix warning None None

Each row is backed by a test in tests/test_redis_cache.py (the file's docstring lists which tests prove which claim). Run make tests-redis-up to see them green.

Troubleshooting

Connection refused. Redis isn't running on the configured host/port. Run redis-cli ping from the WordPress host to confirm reachability.

AUTH required. Set WP_REDIS_PASSWORD (and WP_REDIS_USERNAME for ACL users).

DB mismatch. Make sure WP_REDIS_DATABASE matches what you intend — Redis defaults to DB 0, but if another service uses DB 0 you may want DB 1, 2, etc.

Cache won't flush. We use SCAN + UNLINK scoped to our prefix, so flushes never clobber other prefixes in the same Redis DB. If you see stale data, double-check that WP_REDIS_PREFIX is set the way you expect and that no other code path is writing under that prefix.

Foreign drop-in warning. Another plugin has installed wp-content/object-cache.php. Follow the migration steps above for that plugin before installing ours. The warning links to the right steps for the detected plugin.

Site goes down after enabling. Set define( 'WP_REDIS_DISABLED', true ); in wp-config.php as an instant rollback — the drop-in returns early and WordPress falls back to its default in-memory cache.

Multisite

Use {blog_id} in WP_REDIS_PREFIX so each site has its own namespace and wp_cache_flush on one site doesn't affect the others:

define( 'WP_REDIS_PREFIX', 'site_{blog_id}_' );

The admin tab shows a red warning when it detects multisite without a per-site prefix.