{"slug":"wp-redis-object-cache","title":"wp-redis-object-cache","summary":"Configure, audit, troubleshoot, and extend the Redis Object Cache plugin (`redis-cache`) for WordPress persistent object caching. Covers the `wp-content/object-cache.php` drop-in, `wp redis status|enable|disable|update-dropin`, `WP_REDIS_*` constants, Predis/PhpRedis/Relay client","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-16T14:52:08.482927Z","repo":{"url":"https://github.com/Lonsdale201/wp-agent-skills","stars":22,"forks":2,"license":"MIT","updatedAt":"2026-09-21T19:53:59Z"},"bodyHtml":"<hr>\n<h2>name: wp-redis-object-cache\ndescription: &gt;\nConfigure, audit, troubleshoot, and extend the Redis Object Cache plugin\n(<code>redis-cache</code>) for WordPress persistent object caching. Covers the\n<code>wp-content/object-cache.php</code> drop-in, <code>wp redis status|enable|disable|update-dropin</code>,\n<code>WP_REDIS_*</code> constants, Predis/PhpRedis/Relay client selection, cache groups,\nselective flush, metrics, Query Monitor integration, and correct plugin code\nthat uses <code>wp_cache_*</code> with Redis Object Cache.\nlicense: GPLv3\nmetadata:\nwp-skills-author: \"Soczó Kristóf\"\nwp-skills-contact: \"mailto:lonsdale201@hotmail.com\"\nwp-skills-plugin: \"redis-cache\"\nwp-skills-plugin-version-tested: \"2.8.0\"\nwp-skills-wp-version-tested: \"7.0\"\nwp-skills-php-min: \"7.2\"\nwp-skills-last-updated: \"2026-06-15\"</h2>\n<h1>Redis Object Cache</h1>\n<p>Redis Object Cache is a WordPress persistent object-cache drop-in manager. The plugin being active is not enough: persistent caching only runs when a valid <code>wp-content/object-cache.php</code> drop-in exists, <code>WP_REDIS_DISABLED</code> is not true, and WordPress can connect to Redis.</p>\n<p>This skill is about WordPress/plugin integration with the OSS <code>redis-cache</code> plugin. It is not a Redis server installation or Linux service hardening guide.</p>\n<h2>When to use this skill</h2>\n<p>Trigger when ANY of the following is true:</p>\n<ul>\n<li>The task mentions Redis Object Cache, <code>redis-cache</code>, <code>object-cache.php</code>, persistent object cache, <code>wp redis</code>, <code>WP_REDIS_*</code>, PhpRedis, Predis, Relay, Redis cluster, sentinel, or object-cache diagnostics.</li>\n<li>A plugin stores expensive computed data with <code>wp_cache_get()</code> / <code>wp_cache_set()</code> and the site may have Redis Object Cache enabled.</li>\n<li>The user reports \"Redis plugin is active but not working\", \"Object cache not enabled\", \"Drop-in missing/outdated/invalid\", \"Redis server unreachable\", or \"wp cache flush flushed too much\".</li>\n<li>Code needs cache groups, TTLs, selective flush, non-persistent groups, or Redis Object Cache hooks.</li>\n</ul>\n<h2>Non-destructive checks first</h2>\n<p>Run these before changing anything:</p>\n<pre><code>wp redis status\nwp help redis\nwp eval 'echo defined( \"WP_REDIS_VERSION\" ) ? WP_REDIS_VERSION : \"not-loaded\";'\nwp eval 'var_export( file_exists( WP_CONTENT_DIR . \"/object-cache.php\" ) );'\n</code></pre>\n<p>Do not run <code>wp redis enable</code>, <code>wp redis disable</code>, <code>wp redis update-dropin</code>, <code>wp cache flush</code>, or admin \"Flush Cache\" actions as a casual check. Those commands touch the drop-in or flush Redis data.</p>\n<h2>Mental model</h2>\n<table>\n<thead>\n<tr>\n<th>Layer</th>\n<th>What it means</th>\n<th>Source behavior</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Plugin active</td>\n<td>Admin UI, CLI command, diagnostics, helpers are loaded</td>\n<td><code>redis-cache.php</code> registers the plugin and <code>wp redis</code> command</td>\n</tr>\n<tr>\n<td>Drop-in installed</td>\n<td><code>wp-content/object-cache.php</code> exists</td>\n<td>copied from <code>includes/object-cache.php</code></td>\n</tr>\n<tr>\n<td>Drop-in valid</td>\n<td>Drop-in header matches this plugin URI</td>\n<td>checked by <code>Plugin::validate_object_cache_dropin()</code></td>\n</tr>\n<tr>\n<td>Drop-in current</td>\n<td>Drop-in version matches plugin version</td>\n<td>checked by <code>Plugin::object_cache_dropin_outdated()</code></td>\n</tr>\n<tr>\n<td>Redis connected</td>\n<td><code>$wp_object_cache-&gt;redis_status()</code> returns true</td>\n<td>reported as <code>Connected</code>; otherwise <code>Not connected</code></td>\n</tr>\n</tbody>\n</table>\n<p><code>wp redis status</code> can say <code>Not enabled</code> even when the plugin is active. That usually means the drop-in is missing. If the drop-in exists but Redis is down, the status moves toward <code>Not connected</code>.</p>\n<h2>Status meanings</h2>\n<table>\n<thead>\n<tr>\n<th>Status</th>\n<th>Read it as</th>\n<th>Fix path</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>Disabled</code></td>\n<td><code>WP_REDIS_DISABLED</code> is true</td>\n<td>remove/flip the constant if Redis should run</td>\n</tr>\n<tr>\n<td><code>Not enabled</code></td>\n<td>no valid drop-in</td>\n<td>check Redis connectivity, then enable intentionally</td>\n</tr>\n<tr>\n<td><code>Drop-in is invalid</code></td>\n<td>another object-cache drop-in owns the file</td>\n<td>audit before overwriting; <code>update-dropin</code> replaces it</td>\n</tr>\n<tr>\n<td><code>Drop-in is outdated</code></td>\n<td>plugin updated but drop-in stayed old</td>\n<td>update the drop-in after review</td>\n</tr>\n<tr>\n<td><code>Not connected</code></td>\n<td>drop-in exists but Redis connection failed</td>\n<td>check host, port, socket, auth, TLS, server state</td>\n</tr>\n<tr>\n<td><code>Connected</code></td>\n<td>persistent object cache is active</td>\n<td>proceed with normal cache/API work</td>\n</tr>\n</tbody>\n</table>\n<h2>Configuration constants</h2>\n<p>Define constants in <code>wp-config.php</code>, above the WordPress bootstrap line.</p>\n<p>Basic connection:</p>\n<pre><code>define( 'WP_REDIS_HOST', '127.0.0.1' );\ndefine( 'WP_REDIS_PORT', 6379 );\ndefine( 'WP_REDIS_DATABASE', 0 );\ndefine( 'WP_REDIS_TIMEOUT', 1 );\ndefine( 'WP_REDIS_READ_TIMEOUT', 1 );\ndefine( 'WP_REDIS_RETRY_INTERVAL', null );\n</code></pre>\n<p>Authentication:</p>\n<pre><code>define( 'WP_REDIS_PASSWORD', 'secret' );\ndefine( 'WP_REDIS_USERNAME', 'default' ); // Redis ACL user, when used.\n</code></pre>\n<p>Socket/TLS:</p>\n<pre><code>define( 'WP_REDIS_SCHEME', 'unix' );\ndefine( 'WP_REDIS_PATH', '/var/run/redis/redis.sock' );\n\ndefine( 'WP_REDIS_SCHEME', 'tls' );\ndefine( 'WP_REDIS_SSL_CONTEXT', array(\n    'verify_peer' =&gt; true,\n) );\n</code></pre>\n<p>Prefixing and safe flushes:</p>\n<pre><code>define( 'WP_REDIS_PREFIX', 'example.com:' );\ndefine( 'WP_REDIS_SELECTIVE_FLUSH', true );\n</code></pre>\n<p>If <code>WP_REDIS_PREFIX</code> is not defined, the drop-in maps <code>WP_CACHE_KEY_SALT</code> to <code>WP_REDIS_PREFIX</code>. On shared Redis, set a unique prefix or salt before enabling Redis. Without <code>WP_REDIS_SELECTIVE_FLUSH</code>, a full object-cache flush uses <code>flushdb()</code> for the selected database.</p>\n<p>Performance and behavior:</p>\n<pre><code>define( 'WP_REDIS_CLIENT', 'phpredis' ); // predis, phpredis, relay, credis.\ndefine( 'WP_REDIS_IGBINARY', true );     // only if the igbinary extension is loaded.\ndefine( 'WP_REDIS_MAXTTL', DAY_IN_SECONDS );\ndefine( 'WP_REDIS_FLUSH_TIMEOUT', 5 );\ndefine( 'WP_REDIS_GRACEFUL', true );\ndefine( 'WP_REDIS_DISABLE_METRICS', true );\n</code></pre>\n<p>Groups:</p>\n<pre><code>define( 'WP_REDIS_IGNORED_GROUPS', array( 'my-runtime-only' ) );\ndefine( 'WP_REDIS_UNFLUSHABLE_GROUPS', array( 'my-critical-group' ) );\ndefine( 'WP_REDIS_DISABLE_GROUP_FLUSH', false );\n</code></pre>\n<p><code>WP_REDIS_GLOBAL_GROUPS</code> replaces the plugin's default global groups, it does not merge with them. Prefer <code>wp_cache_add_global_groups()</code> in plugin code unless the whole install is deliberately redefining the global group list.</p>\n<p>Advanced topology:</p>\n<pre><code>define( 'WP_REDIS_SERVERS', array( 'tcp://127.0.0.1:6379' ) );\ndefine( 'WP_REDIS_SENTINEL', 'mymaster' );\ndefine( 'WP_REDIS_CLUSTER', array( 'tcp://10.0.0.1:6379', 'tcp://10.0.0.2:6379' ) );\ndefine( 'WP_REDIS_SHARDS', array( 'tcp://10.0.0.1:6379', 'tcp://10.0.0.2:6379' ) );\n</code></pre>\n<p>Do not use <code>WP_REDIS_SERIALIZER</code>; version 2.7.0 removed it. Use <code>WP_REDIS_IGBINARY</code> when igbinary is installed and desired.</p>\n<h2>Client selection</h2>\n<p>The drop-in chooses a client in this order:</p>\n<ul>\n<li>Default is <code>predis</code>.</li>\n<li>If PHP class <code>Redis</code> exists, default becomes <code>phpredis</code>.</li>\n<li><code>WP_REDIS_CLIENT</code> overrides the default; <code>pecl</code> maps to <code>phpredis</code>.</li>\n<li>Relay is used only when <code>WP_REDIS_CLIENT</code> is set to <code>relay</code>; it is not auto-selected.</li>\n<li>Credis still exists for compatibility but is deprecated.</li>\n</ul>\n<p>Do not assume all topology modes work with every client. Relay in this plugin does not support sharding or cluster mode. Predis handles the broadest pure-PHP topology set because the plugin bundles Predis.</p>\n<h2>WP-CLI behavior</h2>\n<p><code>wp redis status</code> is read-only and prints diagnostics from <code>includes/diagnostics.php</code>.</p>\n<p><code>wp redis enable</code>:</p>\n<ul>\n<li>refuses to enable over a foreign <code>object-cache.php</code>;</li>\n<li>tries to flush Redis with the plugin's Predis helper before copying the drop-in;</li>\n<li>fails if Redis is unreachable;</li>\n<li>fires <code>redis_object_cache_enable</code> with the copy result.</li>\n</ul>\n<p><code>wp redis disable</code>:</p>\n<ul>\n<li>refuses if no drop-in exists;</li>\n<li>refuses foreign drop-ins;</li>\n<li>deletes a valid Redis Object Cache drop-in;</li>\n<li>flushes Redis after successful deletion;</li>\n<li>fires <code>redis_object_cache_disable</code>.</li>\n</ul>\n<p><code>wp redis update-dropin</code>:</p>\n<ul>\n<li>overwrites <code>wp-content/object-cache.php</code>;</li>\n<li>flushes Redis after the copy;</li>\n<li>fires <code>redis_object_cache_update_dropin</code>.</li>\n</ul>\n<p>Treat <code>update-dropin</code> as a deliberate operation. It can replace another plugin's object-cache drop-in.</p>\n<h2>Correct plugin cache usage</h2>\n<p>Use WordPress cache APIs. Do not instantiate Redis directly from normal plugin code.</p>\n<pre><code>$key   = 'report:' . md5( wp_json_encode( $args ) );\n$group = 'myplugin_reports';\n\n$value = wp_cache_get( $key, $group, false, $found );\nif ( ! $found ) {\n    $value = myplugin_build_report( $args );\n    wp_cache_set( $key, $value, $group, HOUR_IN_SECONDS );\n}\n\nreturn $value;\n</code></pre>\n<p>Always use the <code>$found</code> parameter because a cached value may legitimately be <code>false</code>, <code>0</code>, <code>''</code>, or an empty array.</p>\n<p>Use groups intentionally:</p>\n<pre><code>add_action( 'init', static function (): void {\n    wp_cache_add_non_persistent_groups( array( 'myplugin_request_only' ) );\n    wp_cache_add_global_groups( array( 'myplugin_network_config' ) );\n} );\n</code></pre>\n<p>Flush a group only after checking support:</p>\n<pre><code>if ( wp_cache_supports( 'flush_group' ) ) {\n    wp_cache_flush_group( 'myplugin_reports' );\n}\n</code></pre>\n<p>This drop-in reports support for <code>add_multiple</code>, <code>set_multiple</code>, <code>get_multiple</code>, <code>delete_multiple</code>, <code>flush_runtime</code>, and <code>flush_group</code>.</p>\n<h2>Hooks and filters</h2>\n<p>Lifecycle:</p>\n<ul>\n<li><code>redis_object_cache_enable</code></li>\n<li><code>redis_object_cache_disable</code></li>\n<li><code>redis_object_cache_update_dropin</code></li>\n</ul>\n<p>Runtime/cache events:</p>\n<ul>\n<li><code>redis_object_cache_get</code></li>\n<li><code>redis_object_cache_get_multiple</code></li>\n<li><code>redis_object_cache_get_value</code></li>\n<li><code>redis_object_cache_set</code></li>\n<li><code>redis_object_cache_delete</code></li>\n<li><code>redis_object_cache_flush</code></li>\n<li><code>redis_object_cache_flush_group</code></li>\n<li><code>redis_object_cache_error</code></li>\n</ul>\n<p>Behavior filters:</p>\n<ul>\n<li><code>redis_cache_expiration</code> to cap or adjust TTL per key/group.</li>\n<li><code>redis_cache_add_non_persistent_groups</code> to alter groups passed to <code>wp_cache_add_non_persistent_groups()</code>.</li>\n<li><code>redis_cache_validate_dropin</code> to override the plugin's drop-in validation result.</li>\n<li><code>redis_cache_manager_capability</code> or <code>WP_REDIS_MANAGER_CAPABILITY</code> to change admin access from <code>manage_options</code> / <code>manage_network_options</code>.</li>\n</ul>\n<h2>Metrics and diagnostics</h2>\n<p>Metrics are enabled unless <code>WP_REDIS_DISABLE_METRICS</code> is true, but they record only when Redis is connected and the drop-in exposes <code>info()</code> and <code>redis_instance()</code>. <code>WP_REDIS_METRICS_MAX_TIME</code> controls retention; default is one hour.</p>\n<p>Diagnostics intentionally masks <code>WP_REDIS_PASSWORD</code> and password query parameters in <code>WP_REDIS_SERVERS</code>, but still avoid pasting full diagnostics into public tickets without checking for hostnames, usernames, paths, and topology.</p>\n<h2>Critical rules</h2>\n<ul>\n<li>Do not equate \"plugin active\" with \"Redis object cache enabled\". Check the drop-in and status.</li>\n<li>Do not enable/update/disable the drop-in on production without approval. Those operations write <code>wp-content/object-cache.php</code> and may flush Redis.</li>\n<li>Do not use shared Redis without a unique <code>WP_REDIS_PREFIX</code> or <code>WP_CACHE_KEY_SALT</code>.</li>\n<li>Do not rely on selective flush unless both <code>WP_REDIS_PREFIX</code> and <code>WP_REDIS_SELECTIVE_FLUSH</code> are set.</li>\n<li>Do not use <code>wp_cache_get()</code> with <code>false === $value</code> checks for values that may be false. Use <code>$found</code>.</li>\n<li>Do not write directly to core query cache groups unless the <code>wp-query-cache</code> skill says that pattern is safe.</li>\n<li>Do not log raw Redis credentials. The plugin masks diagnostics, your code still must not expose secrets.</li>\n<li>Do not suppress Redis connection failures in application code. Fix the service, socket, auth, TLS, constants, or drop-in state.</li>\n</ul>\n<h2>Cross-references</h2>\n<ul>\n<li>Run <strong><code>wp-query-cache</code></strong> when code touches core query cache groups or <code>last_changed</code> salts.</li>\n<li>Run <strong><code>wp-filesystem-api</code></strong> when implementing a plugin feature that writes drop-ins or generated files.</li>\n<li>Run <strong><code>wp-cli-extending</code></strong> when adding custom maintenance commands around cache warming or purge tasks.</li>\n<li>Run <strong><code>wp-security-audit</code></strong> when exposing cache flush/update actions in admin, AJAX, or REST.</li>\n</ul>\n<h2>References</h2>\n<ul>\n<li>Plugin entry/version: <code>wp-content/plugins/redis-cache/redis-cache.php</code></li>\n<li>Drop-in implementation: <code>wp-content/plugins/redis-cache/includes/object-cache.php</code></li>\n<li>Admin/drop-in lifecycle: <code>wp-content/plugins/redis-cache/includes/class-plugin.php</code></li>\n<li>WP-CLI command behavior: <code>wp-content/plugins/redis-cache/includes/cli/class-commands.php</code></li>\n<li>Diagnostics constants: <code>wp-content/plugins/redis-cache/includes/diagnostics.php</code></li>\n<li>Predis connection/flush helper: <code>wp-content/plugins/redis-cache/includes/class-predis.php</code></li>\n<li>Metrics behavior: <code>wp-content/plugins/redis-cache/includes/class-metrics.php</code></li>\n<li>Official documentation: <a href=\"https://wordpress.org/plugins/redis-cache/\">https://wordpress.org/plugins/redis-cache/</a></li>\n<li>Official documentation: <a href=\"https://github.com/rhubarbgroup/redis-cache\">https://github.com/rhubarbgroup/redis-cache</a></li>\n<li>Verified source paths:\n<ul>\n<li><code>wp-content/plugins/redis-cache/readme.txt</code></li>\n</ul>\n</li>\n</ul>\n","files":[{"path":"SKILL.md","sizeBytes":12230,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-16T14:57:20.893548Z","sha256":"2FF0DCD3AED716D3F9C2673533DCED98B438C912F4BC29199305DEA6B8399B10","sizeBytes":4713},"review":null,"source":{"repositoryUrl":"https://github.com/Lonsdale201/wp-agent-skills","path":"redis-object-cache/wp-redis-object-cache","license":"MIT","commit":"8820ff3c301066297e696611e3bc4ebeb47d1851","subtreeSha":"7794B772882B13CE3202C4B3DE2DCC58EFF95FE00198F9F9B6855A54F1D9A703","lastSyncedAt":"2026-09-22T13:51:11.366991Z"},"reviewedAt":"2026-09-16T15:15:48.483863Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/redis-object-cache/wp-redis-object-cache"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart"},{"target":"git","command":"git clone https://github.com/Lonsdale201/wp-agent-skills.git"}]}