When working with Eloquent in Laravel, you'll often deal with relationships between models—like District belongs to a User, or States has many Districts.
How Laravel loads these relationships matters a lot for performance.
Let’s dive into the two types of loading:
- Lazy Loading
- Eager Loading
Lazy Loading (Default)
Lazy loading means that Laravel delays loading the related data until you actually use it.
For Example:
$users = \App\Models\User::all(); foreach ($users as $user) { echo $user->district->name;}
This will:
Run 1 query
to get all users.
For each user, run another query to get its district.
Total queries: 1 (users) + N (districts)
For 10 users, that’s 11 queries — this is the N+1
problem.
Problem As the number of records grows, this becomes slower and heavier on the database.
Eager Loading
Eager loading tells Laravel to fetch the related data up front, in the same request.
For Example:
$users = \App\Models\User::with(['district'])->get(); foreach ($users as $user) { echo $user->district->name;}
This will:
Run 1 query
to get all posts.
Run 1 query
to get all users related to those posts.
Total queries: 2
Much faster and more efficient.
Multiple Relationships
You can eager load multiple relationships at once
$users = \App\Models\User::with(['district','posts'])->get();
Nested Relationships
You can eager load nested relationships at once
$users = \App\Models\User::with(['district.state.country','posts'])->get();
How We Manually Load Relationships in Laravel
Before Laravel 12.0.8, the standard way to deal with relationships was to manually specify them using with()
.
Example:
$users = \App\Models\User::with(['district.state.country','posts'])->get();
In this example:
We’re manually telling Laravel to load the district and posts relationships.
This avoids N+1
problems.
This level of control is powerful but...
The Problem With Manual Eager Loading
While eager loading is a great solution to the N+1
problem, doing it manually comes with some pain points:
-
Repetition You often repeat the same
with()
calls across multiple controllers, services, or queries. -
Cognitive Load You always need to remember which relationships are used in a view or response.
-
Prone to Bugs Forgetting to eager load a relationship leads to unintentional
N+1
queries. -
Tight Coupling to Usage View or component logic often dictates which relationships should be loaded — not the model itself.
Laravel 12.0.8 to the Rescue: Automatic Eager Loading
After this update, you can now use a config in AppServiceProvider
and eager load all the relationships of any model. No need to use with()
again and again.
Here's how
<?php namespace App\Providers; use Illuminate\Database\Eloquent\Model;use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider{ /** * Register any application services. */ public function register(): void { // } /** * Bootstrap any application services. */ public function boot(): void { Model::automaticallyEagerLoadRelationships(); }}
Laravel automatically includes the district, posts relationships - no with()
, no N+1 query problem.
Let's see with example.
// web.php <?php use Illuminate\Support\Facades\Route; Route::get('/', function () { $users = \App\Models\User::all(); return view('welcome',compact('users'));});
<?php namespace App\Models; use Database\Factories\UserFactory;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Relations\BelongsTo;use Illuminate\Foundation\Auth\User as Authenticatable;use Illuminate\Notifications\Notifiable; class User extends Authenticatable{ /** @use HasFactory<UserFactory> */ use HasFactory, Notifiable; public function district(): BelongsTo { return $this->belongsTo(District::class, 'district_id'); }}
Similarly District
belongs to State
and State
belongs to Country
here is the blade file.
<!doctype html><html lang="en"><head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <title>Automatic Eager Loading</title></head><body><div class="container"> <table class="table"> <thead> <tr> <th scope="col">#</th> <th scope="col">Name</th> <th scope="col">Email</th> <th scope="col">Country</th> <th scope="col">State</th> <th scope="col">District</th> </tr> </thead> <tbody> @forelse($users as $user) <tr> <th scope="row">{{$loop->iteration}}</th> <td>{{$user->name}}</td> <td>{{$user->email}}</td> <td>{{$user->district->state->country->name}}</td> <td>{{$user->district->state->name}}</td> <td>{{$user->district->name}}</td> </tr> @empty <tr> <td colspan="6" class="text-center">No users found</td> </tr> @endforelse </tbody> </table></div> integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script></body></html>
here we have listed all the users with state, district and country. Lets see the result without eager loading.
In the above screenshot, we can see that it is taking
302
query to load all the data with lazy loading. Now let's enable the magic line of code. And this is the result after enabling it.
Now the
302
query has vanished to only 5
queries.
Another Helpful Tip:
Use another configuration on your AppServiceProvider
to avoid Lazy Loading in your local development envirnoment.
Model::preventLazyLoading(!app()->isProduction());
Conclusion
The new automaticallyEagerLoadRelationships() method in Laravel 12.0.8 is a game-changer for optimizing performance and writing cleaner code.
By centralizing which relationships are eager loaded directly inside your models, you can:
- Eliminate repetitive
with()
calls - Avoid the dreaded
N+1
query problem - Keep your controllers and services clean
- Boost your app’s database performance effortlessly
And with the added ability to prevent lazy loading in non-production environments, Laravel now gives you everything you need to catch performance issues early — before they ever hit production.
This small addition makes a big impact in how we work with Eloquent relationships. Start using it in your projects today — and enjoy more performant, readable, and maintainable Laravel apps.
Happy Coding! 🚀 Follow for more Laravel tips and deep dives. 😊

Laravel developer with a passion for clean code, open source, and helping others grow — one line at a time.