Laravel Caching in Practice: What to Cache, TTLs and Invalidation
A practical guide to caching in Laravel: picking the right data to cache, choosing how long to keep it, and clearing it safely when things change.
Caching is one of the quickest ways to make a Laravel application feel faster. It is also one of the easiest ways to show users old or wrong data. The difference comes down to a few simple decisions.
This article walks through those decisions in plain language: what to cache, how long to keep it, how to clear it, and how to know it actually helped.
- Fix slow queries first, then cache what is still expensive.
- Choose a TTL by asking how old the data is allowed to be.
- Clear related keys when data changes, and measure the result.
Why cache at all?
Every time a page rebuilds the same result from scratch, it spends database time, CPU and your users' patience. A cache stores the result of that work so the next request can simply reuse it.
Done well, caching lowers database load and makes response times steady. Done carelessly, it serves outdated data and hides problems that should have been fixed in the query itself.
Deciding what to cache
Good candidates share three things: they are expensive to build, requested often, and fine if slightly old. Dashboards, reports, settings and reference lists usually qualify. Account balances and stock levels at checkout usually do not.
public function index(Request $request)
{
$tenantId = $request->user()->tenant_id;
$report = Cache::remember(
"reports:sales:{$tenantId}",
now()->addMinutes(10),
fn () => SalesReport::forTenant($tenantId)->build()
);
return view('reports.index', compact('report'));
}
Cache::remember() does the whole job in one call: it returns the cached value if it exists, otherwise it runs the closure, stores the result and returns it.
Naming your keys
A clear key name saves hours of debugging later. A simple pattern works well: area:thing:id.
settings:sitefor global settingsproducts:list:page-2for a paginated listreports:sales:42for a report that belongs to tenant 42
Readable keys are easy to find in Redis, easy to clear in groups, and hard to mix up.
Choosing a TTL
The time-to-live (TTL) is really a business question: how old can this data be before someone is confused or harmed?
| Data | Changes | Typical TTL | Clear on write? |
|---|---|---|---|
| App settings | Rarely | Hours or forever | Yes |
| Dashboard numbers | Constantly | 1–10 minutes | Optional |
| Product catalogue | Sometimes | 30–60 minutes | Yes |
| User permissions | Sometimes | Until changed | Always |
Clearing the cache when data changes
There are three common approaches, and most applications use a mix:
- Let it expire. The TTL does the work. Simple, but data can be stale until it expires.
- Clear on change. Remove related keys when the underlying model is saved or deleted.
- Versioned keys. Put a version number in the key, so old entries are simply never read again.
class OrderObserver
{
public function saved(Order $order): void
{
// Tags need a store that supports them, such as Redis.
Cache::tags(["tenant:{$order->tenant_id}", 'reports'])->flush();
}
}
Avoiding a cache stampede
When a popular key expires, many requests may try to rebuild it at the same moment and overload the database. An atomic lock lets only one request rebuild the value while the others wait for a moment.
$report = Cache::get($key);
if ($report === null) {
$report = Cache::lock("lock:{$key}", 10)->block(5, function () use ($key) {
// Another request may have rebuilt it while we waited.
return Cache::remember($key, 600, fn () => buildReport());
});
}
Measuring the result
- Record response times before and after, at the same traffic level.
- Track your hit ratio: a cache that is rarely hit adds complexity without benefit.
- Watch database load, not just page speed.
Summary
Caching is a way to reuse expensive work safely. Pick candidates carefully, set TTLs based on how old the data may be, clear related keys when data changes, and check the improvement with real numbers.
Laravel Caching Masterclass: Cache, Redis & Performance
Step-by-step lessons on everything in this article, plus Redis, full-page caching and cache analytics, applied to a real application.
View Course