Laravel’s Eloquent ORM is one of its standout features, offering an elegant way to interact with your database. However, as your application grows, poorly optimized queries can lead to performance bottlenecks. By leveraging Eloquent caching and query optimization techniques, you can drastically reduce database load, speed up responses, and improve user experience.

In this post, we’ll explore practical strategies to boost your Laravel app’s performance using Eloquent caching and optimization.

Why Optimize Eloquent Queries

Efficient database queries are critical for:

  • Reducing Server Load: Fewer queries mean fewer resources consumed.
  • Improving Response Times: Faster queries lead to better user experiences.
  • Handling High Traffic: Optimized queries ensure your app scales seamlessly.

1. Caching with Laravel’s Cache System

Caching Results That Rarely Change For data that doesn’t change frequently—like site settings, categories, or static lists—you can use Laravel’s rememberForever method:


use Illuminate\Support\Facades\Cache;

$settings = Cache::rememberForever('site_settings', function () {
    return DB::table('settings')->get();
});

This stores the site_settings data indefinitely in the cache, significantly reducing database hits.

Weekly or Monthly Caching

For data that changes periodically, such as reports or analytics, you can set an expiration time with the remember method:


use Illuminate\Support\Facades\Cache;

// Cache for a week
$weeklyReport = Cache::remember('weekly_report', now()->addWeek(), function () {
    return DB::table('reports')->where('type', 'weekly')->get();
});

// Cache for a month
$monthlyReport = Cache::remember('monthly_report', now()->addMonth(), function () {
    return DB::table('reports')->where('type', 'monthly')->get();
});

These caches ensure data freshness while minimizing database queries.

Clearing Cache When Data Changes

When the underlying data changes, always clear the cache to prevent serving stale data:


use Illuminate\Support\Facades\Cache;

Cache::forget('site_settings');
Cache::forget('weekly_report');
Cache::forget('monthly_report');

2. Using Eager Loading to Avoid N+1 Query Issues

The N+1 query problem occurs when your code executes additional queries for related data within a loop. For example:


// N+1 Query Issue
$users = User::all();
foreach ($users as $user) {
    echo $user->profile->bio;
}

This triggers one query to fetch all users and an additional query for each user’s profile. To fix this, use eager loading:


// Eager Loading Fix
$users = User::with('profile')->get();
foreach ($users as $user) {
    echo $user->profile->bio;
}

Eager loading fetches all related data in a single query, drastically reducing database calls.

3. Chunking Large Queries

Fetching thousands of records in one query can exhaust memory. Instead, use Laravel’s chunk method to process large datasets in smaller chunks:


use App\Models\User;

User::chunk(500, function ($users) {
    foreach ($users as $user) {
        // Process each user
    }
});

This approach ensures your app stays efficient even when handling large data sets.

4. Indexing Your Database

Adding indexes to your database tables can significantly speed up queries involving WHERE, JOIN, or sorting operations. For example, if you frequently query users by email, add an index:


Schema::table('users', function (Blueprint $table) {
    $table->index('email');
});

5. Query Optimization with Raw Expressions

For complex queries or bulk updates, raw expressions can be faster than Eloquent methods:


// Update multiple rows efficiently
DB::table('products')
    ->where('stock', '<', 10)
    ->update(['status' => 'out_of_stock']);

While Eloquent is great for most use cases, raw queries can be a better choice for performance-critical operations.

6. Use Lazy Eager Loading for Conditional Relationships

Lazy eager loading is helpful when you conditionally load related data after the initial query. For example:


$users = User::all(); // Initial query
if ($someCondition) {
    $users->load('profile');
}

This avoids fetching unnecessary relationships unless required.

Ready to take your Laravel app to the next level? Don't miss our guide on Laravel Optimization Techniques: Essential Artisan Commands for Production to streamline your app’s deployment and performance.