SYS://VISION.ACTIVE
VIEWPORT.01
LAT 28.0222° N
SIGNAL.NOMINAL
VISION Loading
Back to Blog

Performance Profiling in Laravel: Finding and Fixing Bottlenecks

Shane Barron

Shane Barron

Laravel Developer & AI Integration Specialist

Measure Before Optimizing

Performance optimization without measurement is guesswork. Before changing anything, establish baselines and identify actual bottlenecks. The slowest part of your application might not be where you think it is.

Laravel Debugbar

For development, Debugbar provides immediate visibility:

composer require barryvdh/laravel-debugbar --dev

Debugbar shows queries, memory usage, route information, and timing breakdowns for every request.

Laravel Telescope

Telescope provides deeper insights for debugging:

composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate

Use it to inspect requests, exceptions, database queries, queued jobs, scheduled tasks, and more.

Database Query Analysis

// Enable query logging
DB::enableQueryLog();

// Your code here

// Review queries
dd(DB::getQueryLog());

// Or listen to queries
DB::listen(function ($query) {
    if ($query->time > 100) { // > 100ms
        Log::warning('Slow query', [
            'sql' => $query->sql,
            'time' => $query->time,
        ]);
    }
});

Identifying N+1 Problems

// In AppServiceProvider
public function boot(): void
{
    Model::preventLazyLoading(!app()->isProduction());
}

// This throws an exception when lazy loading occurs in non-production

Profiling with Xdebug and Blackfire

For detailed profiling, use Xdebug's profiler or Blackfire.io:

# Xdebug configuration
xdebug.mode = profile
xdebug.output_dir = /tmp/xdebug

Analyze the cachegrind files with tools like KCachegrind or QCachegrind.

Memory Profiling

// Track memory usage
$start = memory_get_usage();

// Your code

$end = memory_get_usage();
Log::info('Memory used: ' . ($end - $start) / 1024 / 1024 . 'MB');

Production Monitoring

Use APM tools in production:

  • New Relic
  • Datadog
  • Scout APM
  • Laravel Pulse

Common Optimizations

// Route caching
php artisan route:cache

// Config caching
php artisan config:cache

// View caching
php artisan view:cache

// Optimize autoloader
composer install --optimize-autoloader --no-dev

Query Optimization

// Use select to limit columns
User::select(['id', 'name', 'email'])->get();

// Use cursor for memory efficiency
User::cursor()->each(function ($user) {
    // Process one at a time
});

// Add database indexes
Schema::table('orders', function ($table) {
    $table->index(['user_id', 'created_at']);
});

Caching Strategies

// Cache expensive queries
$popularProducts = Cache::remember('popular_products', 3600, function () {
    return Product::withCount('orders')
        ->orderByDesc('orders_count')
        ->limit(10)
        ->get();
});

Conclusion

Profile first, optimize second. Use the right tools for the job, and always measure the impact of your optimizations. Small improvements compound—a 10% improvement in ten places is a 2.6x overall improvement.

Share this article
Shane Barron

Shane Barron

Strategic Technology Architect with 40 years of experience building production systems. Specializing in Laravel, AI integration, and enterprise architecture.

Need Help With Your Project?

I respond to all inquiries within 24 hours. Let's discuss how I can help build your production-ready system.

Get In Touch