Laravel 11 performance & caching — Design Review Checklist — Practical Guide (Jul 3, 2026)
Laravel 11 performance & caching — Design Review Checklist
Level: Intermediate to Experienced
As of July 3, 2026 — applicable mainly to Laravel 10 and 11 (stable), with notes on upcoming features in Laravel 11.
Prerequisites
This article targets engineers familiar with Laravel fundamentals, PHP 8.1+, and web performance concepts. Having experience with queues, Redis, or alternative caching backends will help to fully apply this guidance.
- Laravel 10.x or Laravel 11.x (stable release), PHP 8.1+
- Composer and Laravel Sail or Homestead for local development, or equivalent server setup
- Basic understanding of HTTP caching, Laravel cache drivers, and queues
- Familiarity with profiling tools (Laravel Telescope, Laravel Debugbar, or external APMs)
Hands-on steps for optimising performance and caching
1. Use appropriate cache stores for your environment
Laravel supports multiple cache drivers like file, redis, memcached, database. For production, avoid file caching due to lock contention and I/O performance limits.
Choose Redis or Memcached for distributed, low-latency caching. Redis is generally preferred for its feature set (e.g., sorted sets, pub/sub). Laravel 11 continues to optimise Redis integration, including native async support (still considered preview in 11.x).
// config/cache.php example snippet
'stores' => [
'redis' => [
'driver' => 'redis',
'connection' => 'cache',
],
],
2. Cache route and config optimisations
Leverage Laravel’s built-in route and config caching in all production deployments. Run the following before deploying:
php artisan route:cache
php artisan config:cache
This significantly reduces runtime file loading, especially for large applications with complex config or many route definitions.
3. Select the right cache facade method per use case
Understand the difference between Cache::remember(), Cache::rememberForever(), and Cache::put(), while considering TTL (time to live) values carefully:
remember(): Caches a value, regenerating it on miss with a TTL.rememberForever(): Stores indefinitely, but requires manual invalidation.put(): Writes a value with a specified TTL.
When generating cache keys, use Laravel’s built-in cache prefix features to avoid collisions in shared backends.
4. Use Cache Tags for granular invalidation
Laravel supports cache tags, but only on Redis or Memcached drivers. Tags allow grouping related cache entries for bulk invalidation, which is invaluable in content-heavy apps with partial updates.
// Example: Caching posts under a 'posts' tag
Cache::tags('posts')->put('post_123', $postData, 3600);
// Later, invalidate all posts cached:
Cache::tags('posts')->flush();
5. Consider model caching & query optimisation
Laravel 11 continues support for caching query results, but be cautious about cache staleness with rapidly changing data. Use packages like spatie/laravel-responsecache for HTTP layer caching or genealabs/laravel-model-caching cautiously with invalidation logic.
Complement caching with Eloquent query optimisation: eager loading with with() or using Laravel 11’s improved LazyEagerLoading features to minimise N+1 queries.
6. Use HTTP caching and Laravel’s built-in support
HTTP-level caching is often overlooked but can dramatically cut server load. Laravel 11 supports proper ETag, Last-Modified, and Cache-Control headers via middleware:
// Example middleware snippet in Laravel 11
return response($content)
->header('Cache-Control', 'public, max-age=3600')
->header('ETag', md5($content));
Use remember() or rememberForever() cache calls to back HTTP caching and invalidate caches carefully on state changes.
7. Optimise queues and jobs for cache warming
Leverage Laravel queues for asynchronous cache regeneration after writes, avoiding cache stampedes. Laravel Horizon remains the recommended choice for monitoring queue performance. Cache warming jobs should be idempotent and handle failures gracefully.
Common pitfalls
- Overcaching without expiry: Forever-cached data risks stale content; plan invalidation strategies upfront.
- Locking in file caches: File cache drivers can block under concurrency, slowing requests.
- Cache stampede: High cache miss rates on popular keys; mitigate with atomic locks or refresh pepole caches asynchronously.
- Ignoring query efficiency: Caching slow queries is good, but optimise queries first to avoid unnecessary database load.
- Using cache tags on unsupported drivers: Cache tags only work on Redis or Memcached; fallback drivers ignore tags silently.
- Misaligned TTLs: Avoid arbitrarily long or short time-to-live values; tune based on data volatility and read/write ratios.
Validation strategies
To confirm caching and performance improvements, use a combination of profiling and monitoring:
- Laravel Telescope and Laravel Debugbar to measure cache hits and miss rates during development.
- Benchmark cold and warm requests; verify route & config cache effectiveness by measuring app boot time.
- Use external APM tools (e.g., New Relic, Datadog) to monitor request latency and backend response times in production.
- Enable Redis slow log or monitor Memcached statistics to catch expensive cache commands.
- Auditing log files for any cache-related exceptions or warnings.
Checklist / TL;DR
- ✅ Use Redis or Memcached in production — avoid file or database cache drivers.
- ✅ Always run
route:cacheandconfig:cachein your deploy scripts. - ✅ Choose caching methods carefully:
remember()vsrememberForever()with TTLs aligned to data volatility. - ✅ Utilise cache tags for bulk invalidations if your caching backend supports them.
- ✅ Optimise database queries before caching; use eager loading and Laravel 11’s query features.
- ✅ Implement HTTP caching headers with middleware to reduce server load.
- ✅ Employ queues for cache warming and consider Laravel Horizon for queue monitoring.
- ⚠️ Watch for cache stampedes and implement locking or refresh strategies accordingly.
- ⚠️ Test and profile in development, stage, and production environments.