In Laravel, how do Cache::tags() let you flush a group of cached entries, and which cache stores support tags?
answer
- same tags, same order, to read back
- flush removes entries under ANY listed tag
- redis, memcached, array support tags
- database, file, dynamodb, storage do not
- BadMethodCallException on an unsupported store
basics
~20 sCache::tags(['fx', 'fx:EUR'])->put(...) stores an entry under those tags, and Cache::tags('fx:EUR')->flush() drops every entry carrying that tag. Only tag-capable stores such as redis, memcached and array allow it; the database, file, dynamodb and storage stores throw BadMethodCallException.
solid answer
~40 s`Cache::tags([...])` returns a tagged cache; you `put`, `get`, `remember` and `flush` through it. A tagged entry must be read with the **same tags in the same order**, because the tags become part of the stored key. `Cache::tags(['fx', 'fx:EUR'])->flush()` removes entries tagged with *either* tag, so it is how you invalidate every rate derived from one base currency without knowing each key. Tags are only available on stores that support them — `redis`, `memcached` and `array` among the common ones. The `database`, `file`, `dynamodb` and `storage` stores throw `BadMethodCallException: This cache store does not support tagging.` That matters because a new Laravel 13 app defaults to the `database` store, so tag code that worked on Redis in production can fail locally or after a store change.
code
php · 14 lines<?php
use Illuminate\Support\Facades\Cache;
$tags = ['fx', "fx:{$base}"];
$matrix = Cache::store('redis')->tags($tags)->remember(
'matrix',
600,
fn () => $this->builder->matrixFor($base),
);
// Provider pushed a correction for this base currency:
Cache::store('redis')->tags("fx:{$base}")->flush();go deeper
Recall that tags group entries so one flush clears them, and that the same tags must be passed to read an entry back.
Explain which stores support tags, why the Laravel 13 database default throws BadMethodCallException, and that flushing a tag list is an OR.
Keep tag usage on an explicit tag-capable store, schedule stale-tag pruning on Redis, and choose key versioning where the store may change.
Decide whether tag-based invalidation is worth tying the app to Redis or Memcached, versus versioned keys that work on any store.
## The problem tags solve A currency-converter site caches many derived values per base currency: the raw rate table, a formatted conversion matrix, a chart series, a list of stale pairs. When the rate provider pushes a correction for EUR, you want to invalidate **everything derived from EUR** without tracking every key you ever wrote. Plain `Cache::forget($key)` needs the exact key; `Cache::flush()` wipes the whole store. **Cache tags** sit in between: they label entries so you can drop a group at once. ## The API ```php Cache::tags(['fx', 'fx:EUR'])->put('matrix', $matrix, 600); $matrix = Cache::tags(['fx', 'fx:EUR'])->get('matrix'); Cache::tags('fx:EUR')->flush(); ``` Rules that follow from how Laravel implements tags: 1. **Read with the same tags, in the same order.** The tag set is folded into the stored key, so `Cache::tags(['fx:EUR', 'fx'])->get('matrix')` or plain `Cache::get('matrix')` will not find the entry. 2. **Flushing a list is an OR.** `Cache::tags(['fx', 'fx:EUR'])->flush()` removes entries tagged with `fx`, with `fx:EUR`, or with both. To drop only EUR data, flush only `fx:EUR`. 3. **Everything else works through the tagged cache.** `remember()`, `add()`, `increment()` and `forever()` are all available on the object `tags()` returns. 4. `php artisan cache:clear --tags=fx:EUR` flushes the same group from the command line. ## Which stores support tags `Repository::tags()` checks whether the underlying store has a `tags()` method and throws `BadMethodCallException` (*This cache store does not support tagging.*) when it does not. | Store | Tags? | Notes | |---|---|---| | `redis` | yes | dedicated tagged-cache implementation that deletes tagged entries on flush | | `memcached` | yes | generic tag sets | | `array` | yes | handy in tests | | `database` | **no** | the Laravel 13 default store | | `file` | **no** | | | `dynamodb` | **no** | | | `storage` | **no** | | The practical trap: an app that runs Redis in production but the skeleton's `database` store locally (or `array` in tests, which *does* support tags) can pass tests and still throw on a developer machine, or throw in production after someone switches `CACHE_STORE` to `database` to drop Redis. Check `Cache::supportsTags()` if code must run on several stores, or keep tag usage behind one store you name explicitly: `Cache::store('redis')->tags(...)`. ## How a flush actually works - On the generic tag stores (memcached, array), each tag has a stored identifier, and entry keys are built from those identifiers. `flush()` **resets** the tag's identifier, so old keys become unreachable and age out by TTL or eviction rather than being deleted one by one. - The Redis store tracks each tag's entries and **deletes** them on flush. Its tag bookkeeping can accumulate references to expired entries, which the `php artisan cache:prune-stale-tags` command removes; you can run it from the scheduler. ## When not to reach for tags - If you invalidate one key at a time, `forget()` is simpler and works on every store. - If the grouping is really a version ("rates as of sync #812"), putting a version number in the key — `fx:v812:EUR` — works on every store without tag support. - Tag sets add writes and bookkeeping to every tagged `put`, so tag only what you genuinely need to flush as a group. ## Portability checklist 1. Decide which store owns tagged data and name it in code (`Cache::store('redis')->tags(...)`) rather than relying on the default store. 2. Make local development use the same store, or at least one that supports tags, so the `BadMethodCallException` shows up before production does. 3. Remember that the `array` store used by the skeleton's tests *does* support tags, so passing tests prove nothing about the `database` or `file` stores. 4. Keep the tag list stable and ordered in one place — a small helper returning `['fx', "fx:{$base}"]` — so every read and write uses the identical set. Following these steps keeps tag-based invalidation from becoming an environment-specific bug.
- In Laravel, why does Cache::get('matrix') return null for an entry written with Cache::tags(['fx'])->put('matrix', ...)?The tagged cache builds the stored key from the tag set, so the entry does not live under the plain key `matrix`. Reading it needs the same tagged cache, `Cache::tags(['fx'])->get('matrix')`, with the tags in the same order they were written.
- In Laravel, how can code check at runtime whether the current cache store allows tags?Call `Cache::supportsTags()` (or on a named store, `Cache::store('file')->supportsTags()`). It returns `true` when the underlying store implements `tags()`. Using it lets shared code fall back to key versioning or per-key `forget()` on stores such as `database` or `file` instead of throwing `BadMethodCallException`.
saying these in an interview costs you the question
- Every Laravel cache store supports tags, including database and file
- Flushing tags(['a', 'b']) removes only entries tagged with both a and b
- A tagged entry can be read back with plain Cache::get() and its key
- Unsupported stores silently ignore tags() and write untagged entries
- Cache::flush() is the normal way to invalidate one currency's rates