How does Laravel strict mode help catch N+1 issues?

Laravel is strict mode helps catch N+1 issues by turning a silent performance killer into a loud, immediate error during development. It does this through the preventLazyLoading feature, which is part of the broader Eloquent "strict mode".

How It Works: Throwing an Exception

Normally, when you access a relationship on a model (like $post->author->name), Laravel quietly runs a new database query for each model in a loop. This is the N+1 problem, and it often goes unnoticed because the code still works. it is just slow.

When you enable strict mode, Laravel monitors these relationship accesses. If you try to lazy load a relationship that wasn not explicitly eager-loaded (using with()), it will immediately throw a IlluminateDatabaseLazyLoadingViolationException . This forces you to fix the query in development rather than discovering the performance issue later in production.

How to Enable It?

You typically enable this in your AppServiceProvider is boot() method. It is best practice to only enable it outside of production so your live application doesn not break for users if a lazy load slips through.

use IlluminateDatabaseEloquentModel;

public function boot(): void
{
   // This will throw an exception in local/dev, but not in production
   Model::preventLazyLoading(! $this->app->isProduction());
}

Handling the Exceptions

Once enabled, you ll start seeing these exceptions in your local environment. The fix is straightforward: you need to update your query to eager-load the relationship using with() before you loop over the results.

Before (causes N+1 and will throw an exception):

$posts = Post::all();
foreach ($posts as $post) {
   echo $post->author->name; // Exception thrown here!
}

After (eager-loaded, no N+1, no exception):

$posts = Post::with( author )->get();
foreach ($posts as $post) {
   echo $post->author->name; // Works perfectly
}

Customizing the Behaviour

If throwing an exception is too disruptive for your workflow, Laravel allows you to customize what happens when a lazy loading violation occurs. You can, for example, log the violation instead of throwing an exception.

Model::handleLazyLoadingViolationUsing(function (Model $model, string $relation) {
   $class = $model::class;
   info("Attempted to lazy load [{$relation}] on model [{$class}].");
});

7 Views