DEV Community

Fred Castro
Fred Castro

Posted on

10 Laravel Performance Optimization Tips I Learned After 10+ Years in Production

After 10+ years building scalable web applications with Laravel for everything from startups to government systems, I've learned that performance optimization isn't about premature optimizationβ€”it's about knowing which battles to fight.

Currently leading development for a federal government system (CAPES), I've had to optimize Laravel apps handling thousands of concurrent users. Here are the 10 most impactful performance tips I wish I knew when I started.

1. Eager Loading: Stop the N+1 Query Monster

The #1 performance killer I see in Laravel codebases:

// BAD: N+1 queries
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->user->name; // Query fired for EACH post
}

// GOOD: 2 queries total
$posts = Post::with('user')->get();
foreach ($posts as $post) {
    echo $post->user->name;
}
Enter fullscreen mode Exit fullscreen mode

Impact: Reduced query count from 1,001 to 2 queries in a real project.

2. Database Indexing: The Silent Performance Booster

Add indexes to columns you filter/join on:

Schema::table('posts', function (Blueprint $table) {
    $table->index('user_id');
    $table->index('status');
    $table->index(['category_id', 'published_at']); // Composite index
});
Enter fullscreen mode Exit fullscreen mode

Pro tip: Use EXPLAIN in MySQL to identify missing indexes.

3. Cache Expensive Operations

// Cache database queries
$users = Cache::remember('active_users', 3600, function () {
    return User::where('active', true)->get();
});

// Cache computed values
$stats = Cache::remember('dashboard_stats', 600, function () {
    return [
        'total_users' => User::count(),
        'active_sessions' => Session::where('active', true)->count(),
    ];
});
Enter fullscreen mode Exit fullscreen mode

In production: This reduced our dashboard load time from 2.3s to 180ms.

4. Use Redis for Sessions and Cache

// config/database.php
'redis' => [
    'client' => 'phpredis', // Use phpredis extension, not predis
    'cluster' => false,
    'default' => [
        'host' => env('REDIS_HOST', '127.0.0.1'),
        'password' => env('REDIS_PASSWORD', null),
        'port' => env('REDIS_PORT', 6379),
        'database' => 0,
    ],
],
Enter fullscreen mode Exit fullscreen mode

Why Redis? Memory-based storage = 10-100x faster than database sessions.

5. Optimize Eloquent: Select Only What You Need

// BAD: Fetches all columns
$users = User::all();

// GOOD: Select specific columns
$users = User::select('id', 'name', 'email')->get();

// EVEN BETTER: Use pluck for single column
$emails = User::pluck('email');
Enter fullscreen mode Exit fullscreen mode

6. Queue Heavy Operations

Don't make users wait for emails, notifications, or file processing:

// Dispatch to queue
ProcessVideoUpload::dispatch($video);
SendWelcomeEmail::dispatch($user);

// Chain jobs
ProcessOrder::withChain([
    new SendInvoice($order),
    new UpdateInventory($order),
])->dispatch($order);
Enter fullscreen mode Exit fullscreen mode

Result: Page response time dropped from 4s to 300ms.

7. Optimize Autoloader with Composer

composer dump-autoload --optimize
composer install --optimize-autoloader --no-dev
Enter fullscreen mode Exit fullscreen mode

In production: Always run with optimization flags.

8. Enable OPcache in Production

; php.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0 # Disable in production
opcache.revalidate_freq=0
Enter fullscreen mode Exit fullscreen mode

Impact: 30-50% performance boost for free.

9. Use Chunk for Large Datasets

// BAD: Loads 100k records into memory
User::where('active', true)->get()->each(function ($user) {
    // Process user
});

// GOOD: Process in chunks
User::where('active', true)->chunk(200, function ($users) {
    foreach ($users as $user) {
        // Process user
    }
});
Enter fullscreen mode Exit fullscreen mode

10. Monitor with Laravel Telescope & Horizon

Install in development to identify bottlenecks:

composer require laravel/telescope --dev
composer require laravel/horizon
Enter fullscreen mode Exit fullscreen mode

Telescope shows you:

  • Slow queries
  • Memory usage
  • Request duration
  • N+1 query problems

Bonus: Production Checklist

  • Enable OPcache
  • Use Redis for cache/sessions
  • Run php artisan config:cache
  • Run php artisan route:cache
  • Run php artisan view:cache
  • Use CDN for assets
  • Enable GZIP compression
  • Database connection pooling

My Stack for High-Performance Laravel Apps

After years of optimization, here's what I recommend:

  • Web Server: Nginx + PHP-FPM
  • Cache: Redis (with phpredis extension)
  • Database: PostgreSQL with proper indexes
  • Queue: Redis or RabbitMQ for complex workflows
  • Monitoring: Laravel Telescope + Horizon + New Relic

Wrapping Up

Performance optimization is a journey, not a destination. Start with the low-hanging fruit (eager loading, indexing, caching) and measure the impact.

In my work on the CAPES federal system, these optimizations reduced response times from 3-5 seconds to under 200ms, handling thousands of concurrent users smoothly.

What's your #1 Laravel performance tip? Drop it in the comments!


Building scalable Laravel apps for 10+ years | Currently: Senior PHP/Laravel Developer at CAPES | Available for consulting and architecture reviews

Top comments (0)