You Should Use a Persistent Object Cache: When It Matters and When It Does Not
Site Health recommends an object cache once a site crosses a few size thresholds, and a 200-post blog can cross them. Here is what the test counts, when Redis or Memcached actually helps, and how to enable or silence it.
"You should use a persistent object cache" means WordPress has no object cache drop-in and your site crossed one of a handful of size thresholds, so Site Health suggests keeping query results in Redis, Memcached or APCu between requests. It is a recommendation, not an error. Whether it is worth acting on depends on how much of your traffic reaches PHP at all.
What an object cache does
WordPress already caches query results in memory, but only for the duration of one request. A persistent object cache keeps them in a separate store, so the next request reads options, posts and user data from memory instead of asking MySQL again. It is enabled by a drop-in, wp-content/object-cache.php, which replaces WordPress's built-in cache functions with ones that talk to the store.
That is different from page caching, which skips PHP entirely. On a brochure site where nearly every visitor gets a cached page, an object cache speeds up very little. It pays off where pages cannot be cached: logged-in users, the admin, WooCommerce carts and checkouts, membership areas, search. How to speed up WooCommerce explains which store pages fall into that group.
When Site Health shows it
The test, WP_Site_Health::get_test_persistent_object_cache(), runs only when the environment type is production. It passes straight away if wp_using_ext_object_cache() is true — that is, an object cache drop-in is loaded. Otherwise should_suggest_persistent_object_cache() decides:
| Condition | Default threshold |
|---|---|
| Multisite network | Always suggests |
| Autoloaded options, count | more than 500 |
| Autoloaded options, serialized size | more than 100,000 bytes |
Rows in wp_comments, wp_options, wp_posts, wp_terms or wp_users |
1,000 or more in any one |
If none applies, the result reads "A persistent object cache is not required".
The trap: 1,000 posts arrives sooner than you think
The row counts are not the numbers on your Posts screen. The test reads TABLE_ROWS from information_schema, and wp_posts holds every revision, autosave, attachment, navigation menu item, template part and WooCommerce order still stored as a post. A blog with 150 articles, a few revisions each and their images can pass 1,000 rows.
TABLE_ROWS is also an estimate for InnoDB tables, which the code comments accept as accurate enough. Near the threshold, the result can change after MySQL refreshes its statistics without anything on the site changing.
So the warning on a small site often says more about revision history than about scale. If the autoloaded options are what triggered it, that is a separate problem: Autoloaded options and database bloat covers trimming them, which helps with or without a cache.
Enabling one
- Get a store. Most managed hosts offer Redis or Memcached as a switch in the control panel. On a VPS, install the server and the matching PHP extension. Site Health's note about which services your host "appears to support" refers only to loaded PHP extensions, so confirm the server exists.
- Install a drop-in. An object cache plugin, or the host's own integration, writes
wp-content/object-cache.phpand the connection settings. Use one drop-in only: there is exactly oneobject-cache.phpslot. - Separate sites that share a store. Two WordPress installs on one Redis server need different key prefixes or databases unless the drop-in sets a unique prefix for you; otherwise they can read each other's cached options.
Check that WordPress is using it:
wp eval 'var_dump( wp_using_ext_object_cache() );'
wp cache flush
APCu is a special case: it lives inside the PHP process pool and is not shared with WP-CLI, so wp cache flush from the command line does not clear what PHP-FPM has cached. Redis and Memcached do not have that gap.
What changes once it is on
The obvious change is fewer database queries per request; the admin and logged-in pages benefit most. A less obvious one concerns transients. With an object cache loaded, set_transient() writes to the cache instead of the options table. New transients stop adding rows to wp_options, which is good, but they also become volatile: when the store restarts or runs out of memory and evicts keys, they are gone before their expiry. Plugins are supposed to cope with that, since a transient is never guaranteed to exist.
The _transient_ rows already in wp_options stay there, because WordPress no longer looks at them. Once the cache is confirmed working, they are safe to remove after a backup.
Turning the recommendation off
If you have decided an object cache is not worth it — a fully page-cached site, or a host without one — you can change the decision rather than ignore a yellow item forever:
// Never suggest an object cache.
add_filter( 'site_status_should_suggest_persistent_object_cache', '__return_false' );
// Or raise the thresholds.
add_filter( 'site_status_persistent_object_cache_thresholds', function ( $t ) {
$t['posts_count'] = 20000;
return $t;
} );
Put either in a small must-use plugin, not the theme, so a theme switch does not bring the warning back.
Common mistakes
- Enabling an object cache to fix a slow front end that a page cache would fix better.
- Editing the database directly and forgetting the cache: the old values keep being served until you flush. Clearing every cache layer lists the order.
- Leaving
object-cache.phpbehind after Redis is removed from the server. Depending on the drop-in, the site either falls back silently or fails on every request. - Sharing one store between production and staging without separate prefixes.
Verify
- Site Health shows "A persistent object cache is being used".
wp eval 'var_dump( wp_using_ext_object_cache() );'printsbool(true).- The store's own statistics show hits climbing while you browse the admin.
- Admin page loads and logged-in pages are faster than before the change.
Frequently asked
- Not necessarily. That line lists PHP extensions that are loaded: apcu, redis, relay, memcache or memcached. A loaded redis extension means PHP can talk to a Redis server, not that one exists or that your account may use it. Ask the host for a host, port and password.
- No. The result has the status "recommended". WordPress runs correctly without a persistent object cache; the database simply answers the same queries again on each request.
- WordPress only registers the persistent object cache test when the environment type is production. On a site with WP_ENVIRONMENT_TYPE set to staging, development or local, the test does not run.