Introduction
WordPress object caching with Redis or Memcached stores database query results to improve performance. When the cache fails to invalidate after content updates, visitors see outdated post content, comments, or metadata. This is especially problematic for sites with heavy caching where stale content can persist for the entire cache TTL:
# Check if Redis cache key exists after post update
redis-cli GET "wp:posts:123"
# Returns old post content despite the post being updated in the databaseSymptoms
- Updated post content does not appear on the frontend
- Post title, content, or custom fields show old values
- Changes appear only after manually flushing the cache
- Admin shows correct content while frontend shows stale data
- Cache hit rate is high but data freshness is low
Common Causes
- Custom queries bypassing
WP_Querydo not trigger cache invalidation - External object cache plugin (Redis Object Cache, W3 Total Cache) has a bug
- Cache key generation does not include a version or timestamp component
clean_post_cache()not called after programmatic post updates- Multiple WordPress instances sharing the same Redis/Memcached server with overlapping cache keys
Step-by-Step Fix
- 1.Ensure proper cache invalidation on post save. If you are programmatically updating posts, call the invalidation function:
- 2.```php
- 3.// After updating a post programmatically
- 4.wp_update_post($post_data);
- 5.clean_post_cache($post_id);
- 6.wp_cache_delete($post_id, 'posts');
- 7.wp_cache_delete($post_id . ':meta', 'post_meta');
- 8.
` - 9.Verify the Redis object cache plugin is working. Check the Redis keys:
- 10.```bash
- 11.redis-cli KEYS "wp:*:posts:*" | head -20
- 12.
` - 13.After updating a post, the corresponding key should be deleted or updated.
- 14.Add cache invalidation hooks for custom scenarios:
- 15.```php
- 16.// Ensure cache clears on post save
- 17.add_action('save_post', function($post_id, $post, $update) {
- 18.clean_post_cache($post_id);
// Also clear related term caches $terms = wp_get_post_terms($post_id); foreach ($terms as $term) { clean_term_cache($term->term_id, $term->taxonomy); } }, 10, 3); ```
- 1.Fix cache key collisions in multisite or multi-instance setups. In
wp-config.php: - 2.```php
- 3.// Unique prefix per WordPress instance
- 4.$table_prefix = 'wp1_';
// Or for Redis Object Cache plugin define('WP_CACHE_KEY_SALT', 'wp1_'); ```
- 1.Flush the cache for a specific post using WP-CLI:
- 2.```bash
- 3.wp cache flush
- 4.# Or just the post group
- 5.wp cache delete 123 posts
- 6.wp cache delete 123:meta post_meta
- 7.
` - 8.Debug cache behavior by enabling logging in the Redis Object Cache plugin:
- 9.```php
- 10.define('WP_REDIS_DEBUG', true);
- 11.define('WP_REDIS_LOG', '/var/log/redis-object-cache.log');
- 12.
` - 13.Then monitor which keys are being set, retrieved, and deleted.
Prevention
- Always use WordPress core functions (
wp_update_post,update_post_meta) which trigger cache invalidation automatically - When using direct database queries (
$wpdb->query), manually callclean_post_cache()afterward - Use unique
WP_CACHE_KEY_SALTvalues for each WordPress instance sharing a Redis server - Monitor cache hit/miss ratios to detect invalidation issues early
- Add cache validation to your post update workflow: read the cached value after update and verify it matches
- Keep the Redis Object Cache plugin updated as invalidation bugs are frequently fixed
- Implement a cache warming strategy after bulk content updates to prevent cold cache performance degradation