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:

bash
# 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 database

Symptoms

  • 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_Query do 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. 1.Ensure proper cache invalidation on post save. If you are programmatically updating posts, call the invalidation function:
  2. 2.```php
  3. 3.// After updating a post programmatically
  4. 4.wp_update_post($post_data);
  5. 5.clean_post_cache($post_id);
  6. 6.wp_cache_delete($post_id, 'posts');
  7. 7.wp_cache_delete($post_id . ':meta', 'post_meta');
  8. 8.`
  9. 9.Verify the Redis object cache plugin is working. Check the Redis keys:
  10. 10.```bash
  11. 11.redis-cli KEYS "wp:*:posts:*" | head -20
  12. 12.`
  13. 13.After updating a post, the corresponding key should be deleted or updated.
  14. 14.Add cache invalidation hooks for custom scenarios:
  15. 15.```php
  16. 16.// Ensure cache clears on post save
  17. 17.add_action('save_post', function($post_id, $post, $update) {
  18. 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. 1.Fix cache key collisions in multisite or multi-instance setups. In wp-config.php:
  2. 2.```php
  3. 3.// Unique prefix per WordPress instance
  4. 4.$table_prefix = 'wp1_';

// Or for Redis Object Cache plugin define('WP_CACHE_KEY_SALT', 'wp1_'); ```

  1. 1.Flush the cache for a specific post using WP-CLI:
  2. 2.```bash
  3. 3.wp cache flush
  4. 4.# Or just the post group
  5. 5.wp cache delete 123 posts
  6. 6.wp cache delete 123:meta post_meta
  7. 7.`
  8. 8.Debug cache behavior by enabling logging in the Redis Object Cache plugin:
  9. 9.```php
  10. 10.define('WP_REDIS_DEBUG', true);
  11. 11.define('WP_REDIS_LOG', '/var/log/redis-object-cache.log');
  12. 12.`
  13. 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 call clean_post_cache() afterward
  • Use unique WP_CACHE_KEY_SALT values 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