Bird
Raised Fist0
Laravelframework~8 mins

Lazy loading and N+1 prevention in Laravel - Performance & Optimization

Choose your learning style10 modes available
Performance: Lazy loading and N+1 prevention
HIGH IMPACT
This concept affects database query efficiency and page load speed by reducing unnecessary data fetching and minimizing server response time.
Fetching related data for multiple records in a Laravel application
Laravel
$posts = Post::with('author')->get();
foreach ($posts as $post) {
    echo $post->author->name;
}
Eager loads all authors in a single query, reducing database calls drastically.
📈 Performance Gainsingle query for posts and authors, reducing queries from N+1 to 2, improving LCP
Fetching related data for multiple records in a Laravel application
Laravel
foreach ($posts as $post) {
    echo $post->author->name;
}
This triggers one query for posts plus one query per post to fetch the author, causing many database calls (N+1 problem).
📉 Performance Costtriggers N+1 database queries, increasing server response time and delaying page load
Performance Comparison
PatternDatabase QueriesServer Response TimePage Load ImpactVerdict
Lazy loading causing N+1 queriesN+1 queries (1 + N)High due to many queriesSlower LCP, delays content display[X] Bad
Eager loading with with() method2 queries (main + related)Low due to fewer queriesFaster LCP, quicker content display[OK] Good
Rendering Pipeline
Lazy loading delays fetching related data until accessed, causing multiple queries during rendering. Eager loading fetches all needed data upfront, reducing query count and speeding up server response.
→Server-side Data Fetching
→Network
→Rendering
⚠️ BottleneckServer-side Data Fetching due to multiple database queries
Core Web Vital Affected
LCP
This concept affects database query efficiency and page load speed by reducing unnecessary data fetching and minimizing server response time.
Optimization Tips
1Avoid lazy loading related data inside loops to prevent N+1 queries.
2Use Laravel's with() method to eager load related models in one query.
3Monitor database queries with Laravel Debugbar to detect N+1 problems early.
Performance Quiz - 3 Questions
Test your performance knowledge
What is the main performance problem caused by N+1 queries in Laravel?
AMultiple database queries increasing server response time
BToo much CSS slowing down rendering
CJavaScript blocking the main thread
DImages not loading lazily
DevTools: Network and Laravel Debugbar
How to check: Open Laravel Debugbar in browser, check the number of database queries executed during page load; in Network tab, observe server response time.
What to look for: Look for many repeated queries indicating N+1 problem; fewer queries and faster response times indicate good performance.

Practice

(1/5)
1. What is the main purpose of using with() in Laravel Eloquent queries?
easy
A. To delete related models automatically
B. To load related models eagerly and prevent the N+1 query problem
C. To delay loading related models until they are accessed
D. To paginate the main query results

Solution

  1. Step 1: Understand lazy vs eager loading

    Lazy loading delays loading related data until accessed, causing multiple queries (N+1 problem).
  2. Step 2: Role of with()

    The with() method loads related models eagerly in one query, preventing multiple queries.
  3. Final Answer:

    To load related models eagerly and prevent the N+1 query problem -> Option B
  4. Quick Check:

    Eager loading = with() usage [OK]
Hint: Use with() to load relations early and avoid many queries [OK]
Common Mistakes:
  • Confusing lazy loading with eager loading
  • Thinking with() delays loading
  • Assuming with() deletes data
  • Mixing with() with pagination
2. Which of the following is the correct syntax to eager load the 'comments' relation on a Post model?
easy
A. $posts = Post::with('comments')->get();
B. $posts = Post::load('comments')->get();
C. $posts = Post::eager('comments')->get();
D. $posts = Post::fetch('comments')->get();

Solution

  1. Step 1: Identify Laravel eager loading method

    Laravel uses with() to eager load relations, not load() or others in this context.
  2. Step 2: Check method chaining and syntax

    with('comments') is called before get() to eager load comments with posts.
  3. Final Answer:

    $posts = Post::with('comments')->get(); -> Option A
  4. Quick Check:

    Eager load syntax = with() before get() [OK]
Hint: Remember: with() before get() for eager loading [OK]
Common Mistakes:
  • Using load() statically instead of on model instance
  • Using non-existent methods like eager() or fetch()
  • Calling with() after get()
3. Given the code below, what will be the total number of database queries executed?
 $users = User::all();
foreach ($users as $user) {
echo $user->posts->count();
}
medium
A. N+1 queries, where N is the number of users
B. 1 query
C. N queries, where N is the number of posts
D. 2 queries regardless of users count

Solution

  1. Step 1: Analyze the initial query

    User::all() runs 1 query to get all users.
  2. Step 2: Check relation access inside loop

    Accessing $user->posts triggers a query per user (lazy loading), causing N additional queries.
  3. Final Answer:

    N+1 queries, where N is the number of users -> Option A
  4. Quick Check:

    Lazy loading inside loop = N+1 queries [OK]
Hint: Accessing relations in loop without with() causes N+1 queries [OK]
Common Mistakes:
  • Assuming only 1 query runs
  • Confusing number of queries with posts count
  • Thinking 2 queries run regardless of data size
4. Identify the error in the following code that tries to prevent N+1 queries:
 $orders = Order::with('items');
foreach ($orders as $order) {
echo $order->items->count();
}
medium
A. Incorrect relation name 'items', should be 'item'
B. Loop variable should be $orders not $order
C. Using with() causes lazy loading, should use load()
D. Missing get() after with() to execute the query

Solution

  1. Step 1: Check query execution

    Order::with('items') builds a query but does not execute it without get() or similar.
  2. Step 2: Effect on foreach loop

    Without get(), $orders is a query builder, not a collection, so foreach will error.
  3. Final Answer:

    Missing get() after with() to execute the query -> Option D
  4. Quick Check:

    Always call get() to run query after with() [OK]
Hint: Add get() after with() to fetch data [OK]
Common Mistakes:
  • Forgetting to execute query with get()
  • Assuming with() runs query immediately
  • Confusing relation names without checking model
  • Misunderstanding foreach variable naming
5. You want to display a list of authors with their books and each book's reviews without causing N+1 queries. Which is the best way to write the query?
hard
A. $authors = Author::with('reviews')->get();
B. $authors = Author::with('books')->get(); foreach ($authors as $author) { $author->books->load('reviews'); }
C. $authors = Author::with('books.reviews')->get();
D. $authors = Author::all(); foreach ($authors as $author) { foreach ($author->books as $book) { echo $book->reviews->count(); } }

Solution

  1. Step 1: Understand nested eager loading

    To avoid N+1, load related models and their relations in one query using dot notation.
  2. Step 2: Analyze options for efficiency

    $authors = Author::with('books.reviews')->get(); uses with('books.reviews') to eager load books and their reviews together, preventing multiple queries.
  3. Final Answer:

    $authors = Author::with('books.reviews')->get(); -> Option C
  4. Quick Check:

    Nested eager loading = dot notation in with() [OK]
Hint: Use dot notation in with() for nested relations [OK]
Common Mistakes:
  • Loading relations inside loops causing N+1
  • Not eager loading nested relations together
  • Using wrong relation names
  • Assuming with('reviews') loads nested reviews
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard