Eager Loading vs Lazy Loading in Laravel

1. The N+1 Problem with Lazy Loading

By default, Eloquent uses lazy loading. It means related data is loaded only when accessed.
This often leads to the infamous N+1 query problem.

$users = User::all(); // 1 query
foreach ($users as $user) {
    $user->posts; // +1 query per user ❌
}

100 users = 101 queries 😱


2. Eager Loading - the right way

The solution is eager loading:

$users = User::with('posts')->get(); // 2 queries total ✅

Nested relations:

$users = User::with('posts.comments')->get();

3. Conditional Loading

You don’t always need all relations.

  • Filter related models
$users = User::with(['posts' => fn($q) => $q->where('is_active', true)])->get();
  • Load only if missing
$user->loadMissing('posts');
  • Combine with whereHas
$users = User::withWhereHas('posts', fn($q) => $q->where('is_active', true))->get();

4. Model::shouldBeStrict() – your dev-time guard

Enable strict mode in AppServiceProvider:

use Illuminate\Database\Eloquent\Model;

public function boot(): void
{
    Model::shouldBeStrict();
}

Benefits:

  • Laravel throws exceptions on lazy loading in loops
  • Catches undefined attributes
  • Safer development workflow

For production you can use:

Model::preventLazyLoading(! app()->isProduction());

This way you get exceptions in dev, warnings in prod.


5. Best Practices Checklist ✅

  • Always use with() when you know you’ll need relations
  • Use withCount() for aggregates instead of full relation load
  • For conditional loading, use withWhereHas
  • Enable Model::shouldBeStrict() during development
  • Monitor queries (Laravel Debugbar, Telescope, Clockwork)

Comments (0)
Leave a comment

© 2026 All rights reserved.