Laravel Performance Optimization: 9 Years of Lessons
Performance optimization is critical for modern web applications. After nine years of building Laravel systems — from telecom platforms serving millions of requests to e-commerce backends — I have learned that the biggest gains rarely come from micro-optimizations. They come from architecture, caching, and understanding how your database behaves under load.
1. Eliminate N+1 Queries with Eager Loading
The most common performance killer in Laravel applications is the N+1 query problem. When you load a collection of models and then access a relationship inside a loop, Laravel executes one query per iteration. For 100 users with 10 posts each, that is 1,001 queries instead of two.
// Bad
$users = User::all();
foreach ($users as $user) {
echo $user->posts->count();
}
// Good
$users = User::with('posts')->get();
foreach ($users as $user) {
echo $user->posts->count();
}
Install Laravel Debugbar or Telescope in development and watch the query count. Any page issuing more than 30 queries for a single request deserves a review.
2. Cache Aggressively with Redis
Redis is the single highest-impact addition to most Laravel stacks. Cache expensive queries, computed aggregates, and third-party API responses. On a telecom asset-management system I worked on, adding a Redis caching layer for frequently accessed reference data reduced average API latency by roughly 30%.
$stats = Cache::remember('dashboard.stats', 300, function () {
return Order::selectRaw('COUNT(*) as total, SUM(amount) as revenue')
->where('created_at', '>=', now()->subDay())
->first();
});
Use cache tags for invalidation and set sensible TTLs. Never cache user-specific data without including the user ID in the key.
3. Profile Your Queries
Enable slow query logging in MySQL and PostgreSQL. A missing index can turn a 5 ms query into a 500 ms query under load. Use EXPLAIN ANALYZE on every query that appears in your slow log, and add composite indexes that match your actual WHERE and ORDER BY clauses.
4. Move Work to Queues
Anything that does not need to happen in the request lifecycle — emails, PDF generation, image resizing, webhook dispatch, report building — belongs in a queue. Laravel's queue system with Redis or SQS handles this elegantly. Configure multiple queues with different priorities and run dedicated workers for slow jobs.
5. Optimize the Deployment Pipeline
Run php artisan config:cache, route:cache, and view:cache as part of every production deploy. Use OPcache with opcache.validate_timestamps=0 in production. Deploy with zero downtime using tools like Deployer or Envoyer, and always warm your caches after deployment.
Conclusion
Laravel is fast out of the box, but real-world performance comes from discipline: eager loading, caching, indexing, and queuing. Measure before you optimize, and let profiling data — not intuition — guide your effort.