Skip to content

Cache Expiration Doesn't Work When Using Redis Hashes (WP_REDIS_USE_CACHE_GROUPS) #511

@i-am-chitti

Description

@i-am-chitti

Description

When WP_REDIS_USE_CACHE_GROUPS is enabled (set to true), cache entries stored via wp_cache_set() with an expiration parameter do not expire as expected. The TTL functionality is completely bypassed, causing cached data to persist indefinitely.

Root Cause

The plugin stores cache entries as fields within Redis hashes when grouping is enabled. As documented in the code at

wp-redis/object-cache.php

Lines 950 to 955 in 7b03acd

// Redis doesn't support expire on hash group keys.
if ( $this->_should_use_redis_hashes( $group ) ) {
$redis_safe_group = $this->_key( '', $group );
$this->_call_redis( 'hSet', $redis_safe_group, $key, $data );
return true;
}

Redis does not support setting TTL on individual fields within a hash This means when keys are grouped into hashes, individual expiration times cannot be honored.

Impact & Why This Needs to Be Fixed

This limitation has serious real-world consequences:

  1. Stale locks block critical operations: We use transients with expiration for sync locks (1-hour TTL). When processes terminate unexpectedly, these locks never expire, blocking all future sync operations and requiring manual intervention.

  2. Memory leaks: Cache entries that should expire continue consuming memory indefinitely, leading to bloat over time.

  3. Breaks WordPress Core expectations: The wp_cache_set() function signature includes $expire as a standard parameter. Developers expect this to work consistently—silently ignoring it violates the principle of least surprise.

  4. No workaround available: Setting WP_REDIS_USE_CACHE_GROUPS to false loses the performance and memory benefits of hash grouping

  5. Production reliability issues: Applications relying on cache expiration for rate limiting, temporary tokens, session management, or coordination locks become unreliable in production.

Expected Behavior

When calling:

wp_cache_set('my_key', 'my_value', 'my_group', 3600);

The cached value should automatically be removed after 3600 seconds, regardless of whether WP_REDIS_USE_CACHE_GROUPS is enabled.

Current Workaround

Currently, we have to either:

  • Disable WP_REDIS_USE_CACHE_GROUPS entirely (losing performance benefits)
  • Bypass wp_cache_* functions and use Redis directly for critical expiring keys
  • Implement manual expiration logic in application code

None of these are ideal solutions.

Environment

  • Plugin: WP Redis (latest version)
  • Redis: 6.2+
  • WordPress: 6.x
  • Platform: Pantheon (and local development)
  • WP_REDIS_USE_CACHE_GROUPS: true

This is a fundamental architectural issue that affects anyone using Redis hash grouping with expiring cache entries. A proper fix would greatly improve the reliability and correctness of WordPress caching on Redis.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions