Have you ever noticed your Laravel API getting slower and slower the more records you display in your Vue frontend? You probably ran straight into the dreaded N+1 query problem without even realizing it.

  • What an N+1 query actually is and why it happens
  • How to spot slow queries in your Laravel application
  • How to use eager loading to fix the issue
  • How to test your database performance improvements

What is an N+1 Query?

An N+1 query happens when your code runs one main query to grab a list of items, and then runs a separate query for every single item to get its related data. If you have 50 users, your app runs 1 principal query to get the users, plus 50 extra queries to get each user's profile. That is 51 total database queries for a single page load!

This slows down your server response times. Your Vue frontend ends up waiting longer just to render a simple list of cards or a table.

How to Spot the Problem in Laravel

Laravel makes it very easy to accidentally trigger these extra queries when you loop through Eloquent relationships. For example, if you pass a list of posts to your Vue component via an API, accessing the post author inside a loop triggers a new query every time.

You can catch these issues early by using Laravel Debugbar or checking your database logs during local development. If you see dozens of identical SQL queries running back-to-back, you have found an N+1 problem.

Vue.js development Photo by James Harrison on Unsplash

How to Fix It With Eager Loading

The fix is called eager loading, which means telling Laravel to grab all the related data upfront in a single efficient query using the "with" method. Instead of letting Laravel fetch relationships on demand, you load them all at once before sending the data to your frontend.

Here is how you fix a lazy-loading query inside your Laravel controller:

// Bad: This triggers N+1 queries
$posts = Post::all();
return view('posts.index', compact('posts'));

// Good: This uses eager loading to run only 2 queries total
$posts = Post::with('author')->get();
return view('posts.index', compact('posts'));

The key takeaway is that adding "with('author')" reduces your database trips from dozens down to just two, regardless of how many posts you have.

Common mistakes

A common mistake is using eager loading everywhere "just in case," which can actually waste memory if you do not need the related data. Another mistake is forgetting to eager load nested relationships, such as trying to access a user's profile inside a post author relationship without loading it first.

Open up one of your existing Laravel controllers today, look for loops that access relationships, and add an eager load statement to speed up your API response.