In Laravel, what does php artisan cache:clear actually delete, and why can it wipe another app's keys despite the cache prefix?
answer
- flushes the whole store, not the prefix
- database store: every row of cache
- redis store: FLUSHDB on the cache connection
- optional store argument, --tags and --locks
- Laravel 13 prefix: APP_NAME slug plus -cache-
basics
~20 sphp 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# 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:EURgo deeper
Recall that cache:clear empties the application cache store and that it is separate from the config, route and view caches.
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.
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.
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