Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ChristophAust's avatar

Redis cache tags

Hi there,

so I am in the process of upgrading my app to Laravel 10 and in the upgrade guide I found this:

Redis Cache Tags
Likelihood Of Impact: Medium

Usage of Cache::tags() is only recommended for applications using Memcached. If you are using Redis as your application's cache driver, you should consider moving to Memcached or using an alternative solution.

I do use tagging in cache in a hand full of classes and it seems to work well even after upgrading to version 10. Anyone can elaborate which this was mentioned in the release notes?

I would like to avoid moving away from redis as I also use it for pub/sub.

BR

0 likes
5 replies
LaryAI's avatar
Level 58

The note in the Laravel 10 upgrade guide regarding Redis cache tags is likely due to the fact that Redis, unlike Memcached, does not natively support tag-based cache invalidation. Laravel has implemented a workaround to provide tag support for Redis, but it comes with limitations and potential performance issues, especially as the size of the cached data grows.

The reason for the recommendation against using Redis for cache tagging is that the implementation is not as efficient as it is with Memcached. When you use tags with Redis in Laravel, it stores the tagged cache keys in a "tag set," and when you need to invalidate a given tag, it retrieves all the keys from the tag set and deletes them one by one. This can be a slow operation if there are many keys associated with a tag, and it can also increase the complexity of your cache management.

If you are using Redis and require cache tagging, you have a few options:

  1. Continue using Redis with cache tags, accepting the potential performance implications. If your application is not heavily reliant on cache invalidation by tags or does not operate at a large scale, this might be an acceptable trade-off.

  2. Refactor your caching strategy to avoid the need for tags. This could involve using more specific cache keys that you can invalidate individually or in smaller groups without relying on tags.

  3. Use a combination of Redis for pub/sub and other features, and Memcached for caching where you need to use tags. This would involve configuring your Laravel application to use different cache drivers for different caching needs.

  4. Explore third-party packages or custom solutions that may offer more efficient tag-based caching with Redis.

If you decide to continue using Redis with cache tags, you don't need to change anything immediately, but you should be aware of the potential limitations and monitor your application's performance.

Here's an example of how you might refactor your caching strategy to avoid using tags:

// Instead of using tags, use a structured cache key naming convention.
$cacheKey = "posts.{$postId}.comments";

// When you cache data, you use the structured key.
Cache::put($cacheKey, $comments, now()->addHours(1));

// When you need to invalidate the cache, you can do so directly using the key.
Cache::forget($cacheKey);

In this example, instead of tagging the cache and invalidating by tag, you create a cache key that includes the resource type and identifier, allowing you to target the cache invalidation more precisely.

2 likes
zanderwar's avatar

@LaryAI

and when you need to invalidate a given tag, it retrieves all the keys from the tag set and deletes them one by one.

This statement is incorrect, it would seem.

Laravel simply rotates a hash for the tag set, it does not delete anything one by one, the issue is:

  • The tag sets do not have a TTL
  • The tag sets are not emptied, or removed when a tag is flushed, the hash reference for that tag set is only rotated. None of the cache items within that tag set are flushed, they are left to decay naturally.
  • Using LUA to prune these tag sets when the cache key within it no longers exists (decayed, expired naturally) is extremely inefficient at scale.
  • This means you must have an eviction policy for your redis database configured, otherwise laravel itself will drain all your cache memory slowly but surely due to the bad implementation.

It wasn't perfect by any means, but with an eviction policy it's perfectly fine in handling millions of requests per day at a 99.9% cache hit rate against near 50GB of cache; so my opinion is that removing it even only for Redis is unwarranted

Our application, like many others, uses tags as containers for cache management. Each cache key is uniquely generated based on the request fingerprint (sorting/filtering API results by query params for example, also some other meta we may attach), ensuring that every valid request has its own distinct cache entry. Because of this dynamic generation, it's impossible for us to predict the exact cache key... only the associated tag. As a result, we can only flush caches by their tag, not by individual keys.

Thumbtech's avatar

@zanderwar I've noted your feedback on use of tags in redis cache here and in repo issues. This seems like a recent response, implying that you are working with current laravel code (11? 12?). It seems with the advice to avoid tag use outside of memcache, we won't see the underlying issue resolved for redis users.

May I ask: What/where is the "eviction policy" you refer to here?

Thanks!

ChristophAust's avatar

This AI response was very helpful. Anyone here has dealt with that in any interesting way worth sharing? Otherwise I would look into just refactoring cache tagging out.

pasamsin's avatar

$cacheKey = "posts.{$postId}.comments";

The biggest issue with this code is that you can only delete keys when you know the $postId. For any posts.{?????}.comments outside of that, you cannot delete any cache. In a cache tag structure, you can delete all underlying tags by specifying just the first tag.

1 like

Please or to participate in this conversation.