Goal. By the end of this article, Settings > Redis in your WordPress admin shows "Status: Connected" with a green indicator, and the object-cache.php drop-in is installed in wp-content/. Every WordPress request after that point will read repeat database queries from Redis instead of the database itself.
What object caching is and why Redis beats the default
WordPress has a built-in object cache, but it is non-persistent: every cached query, option, and computed value is stored in a PHP array and thrown away at the end of the request. The next request starts from zero. A Redis object cache replaces that throwaway array with a connection to a real Redis server, so the cached values survive between requests and across PHP workers. The mechanism is documented in the WP_Object_Cache class reference on developer.wordpress.org.
The replacement happens through a file called a drop-in. When WordPress boots, it checks whether wp-content/object-cache.php exists. If it does, WordPress loads that file instead of the built-in class and every call to wp_cache_get(), wp_cache_set(), wp_cache_add(), and friends is routed to Redis. Without the drop-in present, the Redis Object Cache plugin sitting in wp-content/plugins/redis-cache/ is effectively a no-op at cache time: it only renders a status screen in the admin. This is the single biggest trap in Redis setups, and it is why the plugin's dashboard has a big "Enable Object Cache" button rather than turning itself on silently.
Redis object caching sits at a different layer from page caching. A page cache (WP Super Cache, WP Rocket, LiteSpeed LSCache, nginx fastcgi_cache) stores the fully rendered HTML and skips PHP entirely on a hit. A Redis object cache runs after PHP has started: it skips the database queries that would otherwise run during request processing. The two are complementary, not alternatives, which is why the caching layers concept article walks through how they stack. Redis shines exactly in the places a page cache cannot help: logged-in visitors, WooCommerce cart and checkout, /wp-admin/, and anything with per-user output.
A frequent myth is that Redis is only worth it for "large" sites. That is not what the technology does. The benefit of object caching is proportional to how many redundant database queries a request makes, and any WordPress site running Yoast SEO, WooCommerce, a contact-form plugin, or a couple of membership plugins already does plenty. The "big sites only" framing usually comes from managed hosts bundling Redis in higher-tier plans, which is a pricing choice, not a technical one.
Prerequisites
Before you start, you need three things in place. Work through them in order: missing any one of them means the "Enable Object Cache" button will refuse to finish.
- A Redis server you can reach from WordPress. On a single-server setup, Redis runs on
127.0.0.1:6379alongside PHP-FPM. On a managed host, the host gives you a hostname (oftenredis.internalor similar) and a port. In a Docker Compose setup, you add aredisservice todocker-compose.ymland reference it by service name from the WordPress container. On most managed hosts, the control panel or the host's documentation confirms whether Redis is available and which hostname to use. If you have SSH access: verify the server is up by runningredis-cli -h <host> -p <port> ping; it should printPONG. - A PHP Redis client. Either the PhpRedis PECL extension (a compiled C extension, faster) or Predis (pure PHP, bundled with the plugin, slower but no server changes needed). You can check whether PhpRedis is installed from wp-admin under Tools > Site Health > Info > Server, where the "PHP extensions" row lists loaded extensions. If you have SSH access: run
php -m | grep -i redis. If it printsredis, you are set. If PhpRedis is not listed, Predis will be used automatically and you can upgrade later. - WordPress 4.6 or newer, PHP 7.2 or newer. Redis Object Cache 2.7.0 requires at least these versions. The vast majority of modern WordPress sites already meet this bar; if yours does not, upgrade first.
- Write access to
wp-config.phpandwp-content/. The drop-in is copied intowp-content/object-cache.php, and the connection constants go intowp-config.php. IfDISALLOW_FILE_MODSis set, the admin button cannot write the drop-in and you need to use WP-CLI instead (covered below).
On a WordPress multisite network, plan to Network Activate the plugin, not activate it per-site. This has been a requirement since plugin version 2.0.0 and is stated in the Redis Object Cache plugin page.
Step 1: install and activate the Redis Object Cache plugin
Two paths, both valid, both supported in 2.7.0.
Dashboard path. Log in to WordPress, go to Plugins > Add New, search for "Redis Object Cache" by Till Krüss, and click Install Now followed by Activate. You now see a new menu entry under Settings > Redis.
WP-CLI path. From the WordPress root:
wp plugin install redis-cache --activate
Expected output:
Installing Redis Object Cache (2.7.0)
Downloading installation package...
Unpacking the package...
Installing the plugin...
Plugin installed successfully.
Activating 'redis-cache'...
Plugin 'redis-cache' activated.
Success: Installed 1 of 1 plugins.
Do not click any "enable" button yet. Add the wp-config.php constants first, otherwise the drop-in has nowhere to connect to.
Step 2: add the connection constants to wp-config.php
Open wp-config.php through your hosting panel's file manager (or download it via SFTP) and add the following block above the line that reads /* That's all, stop editing! Happy publishing. */. Anything you add below that line is ignored during some bootstrap paths, so the rule from the wp-config.php reference applies here too: new defines go above the marker.
// Redis Object Cache connection
define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_TIMEOUT', 1 );
define( 'WP_REDIS_READ_TIMEOUT', 1 );
// Unique prefix so this site does not collide with other sites on the same Redis
define( 'WP_REDIS_PREFIX', 'yoursite-prod' );
// Optional: database number (0-15) for logical separation on a shared Redis
define( 'WP_REDIS_DATABASE', 0 );
The host value depends on where Redis lives. On a single server with Redis on localhost, 127.0.0.1 is right. On a managed host, use the hostname they give you. In Docker Compose, see the dedicated section below (the answer is redis, not 127.0.0.1).
The WP_REDIS_PREFIX trap
This constant is the most important one in the block for anyone whose Redis server is shared with other WordPress sites, and it is the one tutorials get wrong most often. In plugin version 2.0.0, the Redis Object Cache plugin renamed its own prefix constant from WP_CACHE_KEY_SALT to WP_REDIS_PREFIX to avoid confusion with a WordPress core constant of the same name, as documented in the plugin's changelog. Any tutorial still showing define('WP_CACHE_KEY_SALT', ...) is using v1.x syntax. The legacy alias is still read for backward compatibility, but WP_REDIS_PREFIX is the current, canonical name and the one you should write in new configurations.
The reason the prefix matters: Redis is a single key-value store. Two WordPress sites that both call wp_cache_set('post_123', $data) against the same Redis instance write to the same key and read each other's data. With WP_REDIS_PREFIX set to a unique string per site (yoursite-prod, yoursite-staging, client-a, and so on), every key is namespaced, and the sites cannot corrupt each other. Set it before you enable the drop-in. Changing it later invalidates the existing cache.
If you are running a password-protected Redis, add the credentials too:
define( 'WP_REDIS_PASSWORD', 'your-redis-password' );
// Redis 6+ ACL user, if applicable
define( 'WP_REDIS_USERNAME', 'wordpress' );
Save the file.
Step 3: enable the object cache drop-in
Two equivalent paths. Either path copies redis-cache/includes/object-cache.php into wp-content/object-cache.php.
Dashboard path. Go to Settings > Redis. You see a status panel with fields for Status, Client, Drop-in, Filesystem, Global Prefix, and Host/Port. Near the top is a big Enable Object Cache button. Click it. The page refreshes and Status should switch to "Connected" with a green indicator. Drop-in should read "Valid".
WP-CLI path. From the WordPress root:
wp redis enable
Expected output:
Object cache enabled.
Success: Updated drop-in file.
Both paths do the same thing. The WP-CLI command is useful for automation, Composer-based workflows, containers without admin access, and sites where DISALLOW_FILE_MODS is set so the admin button cannot write files. The plugin's INSTALL.md documents both methods as peers, not alternatives to a mandatory WP-CLI step. The common belief that "plugin version 2.0 made WP-CLI the required way to install the drop-in" is wrong: WP-CLI support has existed since plugin version 1.3.4, and the admin button still works in 2.7.0.
Step 4: verify the connection
You will know it worked when Settings > Redis shows:
- Status: Connected (green)
- Drop-in: Valid
- Client: PhpRedis or Predis (whichever you have)
- Prefix: the value you set in
WP_REDIS_PREFIX
If the Status field shows anything other than "Connected", jump to the troubleshooting section.
If you have SSH access: you can verify the connection from the command line with WP-CLI:
wp redis status
Expected output on a working setup:
Status: Connected
Client: PhpRedis (v5.3.7)
Drop-in: Valid
Disabled: No
Ping: 1
Errors: 0
If Ping is empty or Errors is non-zero, the drop-in is present but cannot actually talk to Redis.
To confirm Redis is actually receiving data, run the following against the Redis server itself:
redis-cli -h 127.0.0.1 -p 6379
> KEYS yoursite-prod:*
> INFO stats
KEYS lists every key written under your prefix (do not run this in production on a large database; SCAN is safer). INFO stats shows keyspace_hits and keyspace_misses. As traffic flows through the site, the hit count should climb steadily; that is the measurable impact. On a typical WordPress front page, the first uncached request populates between 40 and 200 keys, and the second request reads most of them back from Redis.
Step 5: measure the impact
Redis object cache does not advertise itself. The impact shows up in two places:
- Time to first byte on admin pages and logged-in front-end pages. Measure before and after by visiting
/wp-admin/while logged in, with Chrome DevTools > Network, and comparing the main document's Waiting (TTFB) number. On a WooCommerce site with 15 active plugins, I routinely see admin TTFB drop from around 900 ms to 250 ms once Redis takes over. The numbers on your site depend entirely on how query-heavy your plugins are, which is why the high TTFB article walks through the underlying cost model. - Database query count per request. The Query Monitor plugin shows the total queries per request in the admin bar. On a logged-in admin page this number often goes from 400-600 queries on a cold cache to well under 100 on a warm cache, because transients and options that would otherwise hit
wp_optionsnow resolve in Redis. The slow database article explains whywp_optionsbloat is such a common bottleneck, and object caching is the direct fix.
Do not expect an improvement in anonymous front-end TTFB if you already have a well-configured page cache. Page cache hits never run PHP, so Redis never gets a chance to help. The gains live in the requests that bypass the page cache on purpose: admin, logged-in, cart, checkout, REST API, AJAX.
Docker Compose setup
Running WordPress and Redis as separate containers in Docker Compose is the single most common place Redis setups silently fail, and the reason is almost always the same: 127.0.0.1 does not mean what you think it means inside a container. Each container has its own loopback interface, so 127.0.0.1 from the WordPress container points to the WordPress container itself, where Redis is not running. The fix is to use the Redis service name as the hostname.
A minimal working docker-compose.yml:
services:
wordpress:
image: wordpress:php8.3-fpm
depends_on:
- redis
- db
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: change-me
volumes:
- wp-content:/var/www/html/wp-content
redis:
image: redis:7.2-alpine
command: ["redis-server", "--maxmemory", "256mb", "--maxmemory-policy", "allkeys-lru"]
expose:
- "6379"
db:
image: mariadb:11
environment:
MARIADB_ROOT_PASSWORD: change-me
MARIADB_DATABASE: wordpress
MARIADB_USER: wordpress
MARIADB_PASSWORD: change-me
volumes:
wp-content:
And the matching wp-config.php block:
define( 'WP_REDIS_HOST', 'redis' ); // the Compose service name, not 127.0.0.1
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_PREFIX', 'yoursite-prod' );
The --maxmemory and --maxmemory-policy allkeys-lru flags on the Redis command line are worth knowing about. Without a memory cap, Redis grows until the container is killed by the OOM killer. With allkeys-lru, Redis evicts the least-recently-used keys when it hits the cap, which is the correct behavior for a cache (versus a primary data store, where you would want noeviction). The Redis documentation on eviction policies covers the full set of policies if you need something different.
After docker compose up -d, shell into the WordPress container and run wp redis enable && wp redis status to install the drop-in and confirm the connection.
Troubleshooting connection errors
Three errors cover almost every failure.
Status: Not connected or Drop-in: Invalid. Either the drop-in was not installed (the "Enable Object Cache" step was skipped) or it was installed but cannot reach the Redis server. Start with wp redis status and look at the Errors field. If it mentions Connection refused, Redis is not listening on the host and port you configured. If it mentions Authentication failed, your WP_REDIS_PASSWORD is wrong or missing. If it mentions Name or service not known, the hostname does not resolve; in Docker Compose this usually means you wrote 127.0.0.1 instead of the service name.
Redis server went away or intermittent disconnects. The plugin's default WP_REDIS_TIMEOUT and WP_REDIS_READ_TIMEOUT are tight (1 second). On a slow network or during Redis restarts the connection can drop. Raise both to 2 or 3 seconds and set WP_REDIS_RETRY_INTERVAL to 100 (milliseconds) to smooth over transient issues:
define( 'WP_REDIS_TIMEOUT', 2 );
define( 'WP_REDIS_READ_TIMEOUT', 2 );
define( 'WP_REDIS_RETRY_INTERVAL', 100 );
The drop-in works but hit rate stays at zero. The most common cause is that another caching plugin (W3 Total Cache or LiteSpeed Cache with its own object cache enabled) is writing its own object-cache.php on top of the Redis drop-in. Plugin version 2.4.2 and later actively guards against this, but a misconfigured W3TC install can still fight for the file. Check the contents of wp-content/object-cache.php: if it mentions W3 Total Cache or LiteSpeed in the comments, disable the competing plugin's object cache feature and run wp redis enable again.
When you still cannot connect after checking all three, collect: (a) wp redis status output, (b) the full Redis-related block from wp-config.php with the password redacted, (c) the output of redis-cli -h <your-host> -p <your-port> ping run from the same server as WordPress, (d) plugin version from wp plugin list | grep redis-cache, (e) PHP extensions from php -m | grep -i redis, and (f) the current contents of wp-content/object-cache.php (the first 30 lines are enough to see which implementation is installed). With that in hand, any hosting support engineer can tell you in minutes where the break is.
When Memcached makes more sense than Redis
Both Redis and Memcached are persistent object caches that fit the same hole: replace the in-memory WP_Object_Cache with something that survives between requests. Both have a WordPress drop-in. Both work. The honest difference is narrower than it looks:
- Redis supports persistence to disk, replication, pub/sub, and richer data types. For a WordPress object cache, most of those extras are unused, but the persistence-to-disk feature is useful on a VPS where you restart Redis occasionally and do not want to warm the cache from scratch every time.
- Memcached is simpler and slightly faster at the raw key-value operations WordPress actually performs. If your host offers Memcached and not Redis, that is a reasonable choice, not a compromise. The community-maintained Memcached Object Cache drop-in fills the same role as Redis Object Cache.
My default recommendation in 2026 is Redis, because it is what every managed WordPress host supports and what most hosting tutorials assume. But if you inherit a server with Memcached already running and tuned, there is no reason to rip it out for Redis. The win is running a persistent object cache at all. Which one matters less than whether the drop-in is present and the hit rate is climbing.