WordPress Object Cache Example: Cache Plugin Data Safely
Use the WordPress Object Cache correctly with cache groups, the found flag, invalidation, persistent-cache awareness, and WP-CLI debugging.
Published
April 20, 2026
Reading Time
3 min read
Updated
April 20, 2026

Implementation Notes
Extension points, code paths, and implementation choices that should survive contact with production.
Best For
WordPress developers, agencies, and technical teams building custom plugin or theme functionality with cleaner operational defaults.
Primary Topics
Editorial Focus
Build Pattern: Extension points, code paths, and implementation choices that should survive contact with production. Updated on April 20, 2026.
Full Report
Last reviewed: April 20, 2026
The WordPress Object Cache is often misunderstood. Developers use wp_cache_set(), then expect the value to survive across requests on every site. That only happens when a persistent object cache drop-in is installed. Without one, the default object cache lives only for the current request.
This guide shows how to use the Object Cache safely in plugin code. It explains when object cache is useful, how it differs from transients, and how to avoid false cache hits.
Who this guide is for
This article is for WordPress plugin developers, performance engineers, and site operators working with expensive queries, repeated calculations, or persistent object cache backends such as Redis or Memcached.
Object cache vs transients
Use the Object Cache when the value is a runtime performance optimization and can be regenerated. Use the Transients API when you want WordPress to store temporary data even on sites without persistent object cache. If persistent object cache is configured, transients may use it underneath.
Basic cache wrapper
<?php
function vulnwp_get_cached_review_count( $post_id ) {
$post_id = absint( $post_id );
if ( ! $post_id ) {
return 0;
}
$cache_key = 'review_count_' . $post_id;
$cache_group = 'vulnwp_reviews';
$found = false;
$count = wp_cache_get( $cache_key, $cache_group, false, $found );
if ( $found ) {
return (int) $count;
}
$count = vulnwp_calculate_review_count( $post_id );
wp_cache_set( $cache_key, (int) $count, $cache_group, 10 * MINUTE_IN_SECONDS );
return (int) $count;
}
The important part is the $found parameter. wp_cache_get() returns false when a value is missing, but false could also be a legitimate cached value. The $found flag distinguishes those cases.
Delete cache when source data changes
function vulnwp_delete_review_count_cache( $post_id ) {
wp_cache_delete( 'review_count_' . absint( $post_id ), 'vulnwp_reviews' );
}
add_action( 'save_post_post', 'vulnwp_delete_review_count_cache' );
add_action( 'deleted_post', 'vulnwp_delete_review_count_cache' );
Expiration is not a complete invalidation strategy. If the value depends on post data, delete the cache when that data changes.
Cache keys and groups
Use clear cache groups for plugin-owned values. Groups make debugging easier and allow some cache backends to flush or inspect related values more safely. Cache keys should include the arguments that change the result, but they should not include raw unsanitized request data.
$cache_key = sprintf(
'leaderboard_%d_%s',
absint( $category_id ),
sanitize_key( $period )
);
Persistent cache detection
Do not require persistent object cache for correctness. The feature should still work when the cache is request-only. If the feature only performs well with Redis or Memcached, document that operational dependency clearly.
if ( wp_using_ext_object_cache() ) {
// A persistent object cache drop-in is active.
}
Multiple cache reads
If a feature needs many values at once, repeated single-key lookups can become noisy. Newer cache APIs support multiple get, set, and delete operations, but support varies by object cache backend. Check support before relying on advanced operations.
if ( wp_cache_supports( 'get_multiple' ) ) {
$items = wp_cache_get_multiple(
array( 'review_count_10', 'review_count_11' ),
'vulnwp_reviews'
);
}
Do not blindly call advanced cache operations against every site. WordPress polyfills some functions, and object cache drop-ins differ in what they can do efficiently.
Debug with WP-CLI
When WP-CLI is available, cache commands can help confirm whether values are being written, read, or flushed. This is useful during deployment and performance testing.
wp cache get review_count_123 vulnwp_reviews
wp cache delete review_count_123 vulnwp_reviews
wp cache type
Be careful with global flushes on production. Flushing the entire object cache can create a sudden burst of database queries.
Production checklist
- Treat object cache as an optimization, not permanent storage.
- Use the
$foundparameter withwp_cache_get(). - Use plugin-specific cache groups.
- Normalize input before building cache keys.
- Delete cache entries when source data changes.
- Do not store secrets or user-private data under global keys.
- Document whether persistent object cache is expected.
Common mistakes
- Assuming persistence exists. Default object cache is request-scoped.
- Ignoring
$found. Cachedfalsevalues can be mistaken for misses. - Using generic groups. Plugin-owned cache should be easy to identify.
- No invalidation. Stale cached data causes support issues.
- Flushing the whole cache casually. A global flush can hurt unrelated parts of the site.
Related reading
If you need cross-request temporary data without depending on an object cache drop-in, read our Transients API example. For external API calls, pair this with the HTTP API example.


