magento / magento/magento2

cache:id_tags:* reverse-index keys accumulate indefinitely when using Redis/Valkey cache backend

Open
#41,004 8 comments 1 reaction 1 assignee View on GitHub

@engcom-Hotel is already working on this.

Since Jul 17, 2026.

Area: Cache Component: Cache Issue: Confirmed Priority: P2 Progress: ready for grooming Reported on 2.4.9 Reproduced on 2.4.x Triage: Dev.Experience
Dominant language
PHP
Stars
12.2k
Forks
9.4k
PR merge metrics
No merged PRs in 30d

Description

Preconditions and environment
  • Magento Open Source 2.4.9
  • Valkey cache backend (Redis)
  • Cache backend:
    • DB0: default cache
    • DB1: full page cache
    • DB2: sessions

Environment used for testing:

  • Valkey 8.1.1 (redis_version: 7.2.4)
  • phpredis 6.3.0
Steps to reproduce
  1. Enable Redis/Valkey cache:
    • DB0: default cache
    • DB1: full page cache
    • DB2: sessions
  2. Run a large site in production for months.
Expected result

When cache entries are invalidated by tags, all associated metadata should eventually be removed, including:

cache object
cache:tags:* membership
cache:id_tags:* reverse index

No unbounded growth of reverse-index keys should occur during normal production use.

Actual result

cache:id_tags:* keys appear to accumulate indefinitely during long-running production usage.

This results in:

steadily increasing Redis/Valkey memory usage
slower cache operations
large metadata structures despite a relatively small active cache
cache databases growing to several gigabytes over time

Additional information
Problem

After normal Magento operation (product saves, indexing, cache invalidation, cron, frontend traffic), the number of cache:id_tags:* keys continuously grows.

Over time this results in:

  • millions of cache:id_tags:* keys
  • hundreds of MB consumed by tag metadata
  • significantly slower cache invalidation
  • increased Redis/Valkey memory usage
  • much slower bin/magento cache:flush

Example after several months of production, right after bin/magento cache:flush:

DB0 keys: ≈ 2,720,000
cache:id_tags:* 2,622,778 keys

cache:tags:f73_BLOCK_HTML
MEMORY USAGE ≈ 370 MB

cache:tags:f73_CAT_P
MEMORY USAGE ≈ 370 MB

Valkey memory: ≈ 2.7 GB

Investigation

After flushing only cache databases:

valkey-cli -n 0 FLUSHDB
valkey-cli -n 1 FLUSHDB

(Session database was intentionally preserved.)

The cache immediately returned to:

DB0: 916 keys
DB1: 45 keys
DB2: 460 session keys

Valkey memory dropped dramatically:

Before: used_memory ≈ 2.7 GB
After: used_memory ≈ 30 MB

Magento continued working normally.

Only a few requests later:

cache:id_tags:* = 809

which is expected.

This suggests the cache can be rebuilt from a very small baseline, while the long-term metadata growth is what eventually consumes the majority of Redis memory.

Observations

For sampled keys such as:

cache:id_tags:f73_BLOCK_...

the corresponding cache object no longer exists.

The cache item itself has been removed, while the reverse-index entry still exists.

Source code observations

Symfony::remove() performs:

$this->adapter->onRemove($cleanId);
$cache->deleteItem($cleanId);

which correctly removes reverse indices.

However bulk invalidation paths eventually execute:
$this->adapter->deleteByIds($ids);

It is not obvious that deleteByIds() removes the corresponding cache:id_tags:* entries.

During cache:flush, Redis MONITOR showed numerous operations such as:
SREM cache:all_ids ...
but no visible deletion of cache:id_tags:*.

Suggested investigation

Please verify that all bulk cache invalidation paths (especially deleteByIds()) correctly remove the associated cache:id_tags:* reverse-index entries (created by RedisTagAdapter::onSave()), as they appear to accumulate indefinitely during normal operation.

Particular attention may be warranted for the interaction between:

Symfony::clean*()
RedisTagAdapter::deleteByIds()
RedisTagAdapter::onRemove()

to ensure reverse-index cleanup occurs for all invalidation paths.

If this behavior is intentional, clarification on the expected lifecycle of cache:id_tags:* keys would also be appreciated, as they appear to accumulate significantly over time in production environments.

Release note

No response

Triage and priority
  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.