skip to content

In Laravel, what does php artisan cache:clear actually delete, and why can it wipe another app's keys despite the cache prefix?

level: middleimportance: should knowfreq 40%

answer

  1. flushes the whole store, not the prefix
  2. database store: every row of cache
  3. redis store: FLUSHDB on the cache connection
  4. optional store argument, --tags and --locks
  5. Laravel 13 prefix: APP_NAME slug plus -cache-

basics

~20 s

php artisan cache:clear calls flush() on the default or named store, which ignores the key prefix: the database store deletes every cache row and the Redis store runs FLUSHDB, so apps sharing that table or database lose keys too.

solid answer

~40 s

`cache:clear` resolves a store (the default, or `php artisan cache:clear redis`) and calls `flush()`. With `--tags=fx:EUR` it flushes only that tag group, and with `--locks` it clears only atomic locks. `flush()` is store-wide and **does not respect the prefix**: the `database` store deletes every row in `cache`, the `redis` store runs `FLUSHDB` on the cache connection's database (index `1` by default), and the `file` store deletes the cache data directories. The prefix — `Str::slug(APP_NAME).'-cache-'` in Laravel 13 — only namespaces keys on reads and writes, so two apps sharing one Redis database stay apart until one of them flushes. `cache:clear` does not touch the config, route or view caches; those have their own `:clear` commands.

code

bash · 11 lines
bash
# Whole default store (dangerous on a shared Redis database)
php artisan cache:clear

# A named store only
php artisan cache:clear redis

# Only one tag group, on a tag-capable store
php artisan cache:clear redis --tags=fx:EUR

# One key
php artisan cache:forget fx:rates:EUR

go deeper

for a junior

Recall that cache:clear empties the application cache store and that it is separate from the config, route and view caches.

for a middle

Explain that flush ignores the prefix, what it deletes on the database, Redis and file stores, and the store argument plus the --tags and --locks options.

for a senior

Keep deploy scripts off full flushes on shared stores, isolate apps by Redis database or table, and prefer forget or tag flushes to avoid a cold-cache stampede.

for a principal

Decide which apps may share cache infrastructure and who is allowed to flush it, weighing isolation against the cost of more databases or servers.

## What the command does `php artisan cache:clear` is `Illuminate\Cache\Console\ClearCommand`. Its signature is: ```bash php artisan cache:clear {store?} {--tags=} {--locks} ``` 1. It resolves the named store, or the default store when no argument is given. 2. With `--locks` it calls `flushLocks()` instead and returns (tags cannot be combined with `--locks`). 3. Otherwise, with `--tags=a,b` it wraps the store in a tagged cache; without tags it uses the whole store. 4. It calls `flush()`, deletes compiled real-time facade files from `storage/framework/cache`, and fires `cache:clearing` / `cache:cleared` events around the flush. For one key there is `php artisan cache:forget fx:rates:EUR` (with an optional store argument), the command-line twin of `Cache::forget()`. ## What `flush()` deletes, per store | Store | What `flush()` does | Scope | |---|---|---| | `database` | `DELETE` of every row in the `cache` table | the whole table | | `redis` | `FLUSHDB` on the cache connection | the whole Redis database (index `REDIS_CACHE_DB`, default `1`) | | `file` | deletes the directories under the cache path | the whole cache directory | | `array` | empties the in-process array | this process only | | tagged cache (`--tags`) | invalidates the listed tags | only entries under those tags | Laravel's documentation states it directly: flushing the cache does not respect the configured cache prefix and removes every entry. ## Why the prefix does not protect you The prefix exists so that two applications can **share** a store without their keys colliding. It is prepended on every `get`, `put` and `forget`: - Laravel 13 default: `Str::slug(APP_NAME).'-cache-'`, for example `fx-converter-cache-` for an app named "FX Converter". - Laravel 12 and earlier used underscores (`fx_converter_cache_`). But `flush()` does not iterate keys by prefix; it empties the table, the Redis database or the directory. Picture a currency converter and its admin back-office, both pointed at the same Redis server with the default `REDIS_CACHE_DB=1`. They never read each other's keys, yet running `cache:clear` in the back-office deploy script empties the converter's rate cache too, and every visitor's request suddenly calls the rate provider. Ways to keep flushes contained: - Give each app its own Redis database index (`REDIS_CACHE_DB`) or its own server. - On the database store, give each app its own `cache` table (`DB_CACHE_TABLE`) or connection. - Prefer **targeted invalidation** — `Cache::forget()`, `cache:forget`, or `--tags` on a tag-capable store — over a full flush in deploy scripts. - Anything else stored in the same Redis database is flushed as well. The skeleton's `redis` cache store uses a separate `cache` connection (database `1`), while the `default` connection other Redis features use points at database `0`. ## The Laravel 13 prefix change on upgrade The upgrade guide lists the hyphenated prefix as a low-impact change. Apps whose `config/cache.php` defines `prefix` keep their value. Apps that relied on the framework's fallback config get new keys after upgrading, which behaves like a cold cache on first deploy. Setting `CACHE_PREFIX` (and `REDIS_PREFIX`) explicitly keeps the old names. ## What `cache:clear` does not clear `cache:clear` only touches the **application data cache**. The compiled configuration, route and view caches are files under `bootstrap/cache` and `storage/framework/views`, each with its own `:clear` command. Running `cache:clear` after editing `.env` on a server with cached config changes nothing about the config. ## A safer habit for deploys Many deploy scripts run `cache:clear` out of habit. For the currency converter that throws away every cached rate, so the first minutes after each deploy hammer the rate provider. A calmer sequence: 1. Ask whether the deploy actually changed the **shape** of any cached value. If not, leave the data cache alone. 2. If one structure changed, bump a version inside its key (`fx:v2:rates:EUR`) so new code reads new keys while old entries expire on their own. 3. If a group must go, flush only that group with `--tags`, or forget known keys with `cache:forget`. 4. Reserve a full `cache:clear` for stores the app owns alone, and run it when traffic is low. This keeps the cache warm across releases and keeps one app's deploy from emptying another app's cache.

  • In Laravel, how do you invalidate one currency's cached rates from the command line without flushing the whole store?
    Use `php artisan cache:forget fx:rates:EUR` for a single key, optionally with a store name, or `php artisan cache:clear redis --tags=fx:EUR` if the entries were written through `Cache::tags()` on a tag-capable store. Both leave unrelated keys, and other apps sharing the store, untouched.
  • In Laravel 13, why might an upgraded app see a cold cache right after deploying the upgrade?
    The framework's fallback cache prefix changed from underscores to hyphens (`..._cache_` to `...-cache-`). An app that never defined `prefix` in its own `config/cache.php` now reads and writes different key names, so existing entries are ignored. Setting `CACHE_PREFIX` to the old value keeps the keys stable.

saying these in an interview costs you the question

  • cache:clear only deletes keys that start with this app's cache prefix
  • cache:clear also clears the cached config, routes and compiled views
  • The cache prefix makes it safe for two apps to flush one Redis database
  • cache:clear --tags works on the default database store
  • Cache::flush() on the database store deletes only expired rows