Skip to content

@Indexed secondary index keys are not expired when @RedisHash(timeToLive=…) entity expires #3255

@themohamedsabbah

Description

@themohamedsabbah

Description

When a Redis hash entity is annotated with @RedisHash(timeToLive = …) and includes fields marked with @indexed, Spring Data Redis correctly sets a TTL on the primary hash key (e.g., Session:123). Upon expiration, the primary hash is removed automatically.
However, the secondary index sets (e.g., Session:userId:456) are never assigned a TTL and remain in Redis indefinitely, even after the associated entity has expired.

Current Behavior

@RedisHash(timeToLive = 3600)
public class Session {
    @Id String id;
    @Indexed String userId;
}

Generated Redis commands (on save):

HSET Session:123 id "123" userId "456"
EXPIRE Session:123 3600
SADD Session:userId:456 "123"
# ← No EXPIRE on the index key!

After 1 hour:

  • Session:123 → deleted
  • Session:userId:456 → still exists (stale index entry)

Impact

  • Stale index data: Index points to non-existent entities.
  • Unbounded memory growth: For high-churn, short-lived entities (e.g., user sessions, auth tokens), index sets accumulate forever.
  • Operational burden: Requires manual cleanup or external expiration logic.

Proposed Solution
Extend @indexed with an optional flag:

@Indexed(expireWithEntity = boolean, default = false)

When expireWithEntity = true, Spring Data Redis should:

  • Apply the same TTL as the entity to each generated index set key upon save.
  • Optionally clean up empty index sets on expiration (if feasible).

Example:

@RedisHash(timeToLive = 3600)
public class Session {
    @Id private String id;

    @Indexed(expireWithEntity = true)
    private String userId;
}

Expected Redis commands:

HSET Session:123 ...
EXPIRE Session:123 3600
SADD Session:userId:456 "123"
EXPIRE Session:userId:456 3600   # ← Now expires with entity

Backward Compatibility

  • Default value: expireWithEntity = false
  • Existing applications unchanged
  • Opt-in only for use cases needing index TTL synchronization

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions