back to articles
Laravel
Performance

Optimizing API Performance with Redis Caching in Laravel

Deep dive into implementing multi-layer Redis caching strategies to dramatically reduce API response times and database load in production Laravel applications.

Mar 2026·8 min read

In high-traffic Laravel applications, database queries are the primary bottleneck. Redis caching, implemented across multiple layers, can reduce API response times by over 80% and cut database load significantly.

Why Redis Over Other Cache Drivers?

Laravel supports file, database, Memcached, and Redis drivers. Redis stands out for its ability to handle complex data structures, atomic operations, and tag-based invalidation — all critical for a production caching layer.

Layer 1: Tagged Query Result Caching

The most impactful layer is caching expensive query results with cache tags, so related entries can be invalidated atomically when data changes.

php
$users = Cache::tags(['users', 'reports'])
    ->remember("users.active.page.{$page}", 3600, function () {
        return User::active()
            ->with('roles', 'permissions')
            ->paginate(20);
    });

// Invalidate only affected tags on mutation
Cache::tags(['users'])->flush();

Layer 2: HTTP Response Caching Middleware

For read-heavy public endpoints, caching the entire serialized JSON response eliminates application-layer processing entirely. A middleware intercepts the request before it reaches the controller.

php
public function handle(Request $request, Closure $next): Response
{
    $key = 'api:' . sha1($request->fullUrl());

    if (Cache::has($key)) {
        return response()->json(Cache::get($key), 200, ['X-Cache' => 'HIT']);
    }

    $response = $next($request);
    Cache::put($key, $response->getData(), now()->addMinutes(5));

    return $response->withHeaders(['X-Cache' => 'MISS']);
}

Preventing Cache Stampedes

A cache stampede occurs when a cache entry expires and multiple concurrent requests flood the database simultaneously. Laravel's flexible cache handles this with probabilistic early expiration:

php
$value = Cache::flexible('expensive-query', [30, 60], function () {
    return DB::table('reports')->selectRaw('...')->get();
});

Monitoring Cache Health

  • ▸Track hit/miss ratios with Redis INFO — target >90% hit rate
  • ▸Alert when cache memory usage exceeds 75% of maxmemory
  • ▸Log cache misses for slow queries to identify caching gaps
  • ▸Use cache:clear strategically — never blindly in production

With tagged query caching, HTTP response caching, and stampede prevention you can scale your Laravel API to handle orders of magnitude more traffic without proportional database costs.