---
title: Eager Load Relationships to Prevent N+1 Queries
impact: CRITICAL
impactDescription: prevents N+1 query explosion that causes severe performance degradation in production
tags: n+1, eager-loading, eloquent, performance, with, laravel
---

## Eager Load Relationships to Prevent N+1 Queries

Accessing a relationship inside a loop without eager loading fires one query per iteration. With 1000 posts, that is 1001 queries. Always eager load with `with()` when you know you'll access the relationship.

**Wrong:**

```php
// Executes 1 + N queries (one per post)
$posts = Post::all();

foreach ($posts as $post) {
    echo $post->author->name;   // <- SELECT * FROM users WHERE id = ? (×N)
    echo $post->category->name; // <- SELECT * FROM categories WHERE id = ? (×N)
}
```

**Correct:**

```php
// Executes exactly 3 queries total
$posts = Post::with(['author', 'category'])->get();

foreach ($posts as $post) {
    echo $post->author->name;
    echo $post->category->name;
}

// Nested relationships
$posts = Post::with(['author.profile', 'tags'])->get();

// Selective columns to reduce memory
$posts = Post::with(['author:id,name,avatar'])->get();

// Conditional eager loading
$posts = Post::with(['comments' => function ($q) {
    $q->where('approved', true)->latest()->limit(5);
}])->get();
```

**Detection signal:**
- Any `->relationship` access inside a `foreach`, `map`, `each`, or `Collection` method without preceding `with()`
- Use Laravel Telescope or Debugbar in development to detect N+1 — queries > 10 for a single request is a red flag

**Also applies to:**
```php
// WRONG: counting without withCount
$posts->each(fn($p) => $p->comments->count()); // N queries

// CORRECT: withCount
Post::withCount('comments')->get(); // 1 query
```
