# Stop using `Repo.preload` in loops - use `preload` in queries

Calling `Repo.preload/2` inside `Enum.map` or comprehensions creates N+1 queries - one query to fetch the parent records, then **one additional query for each parent** to load associations. Use Ecto's query `preload` to load all associations in a single database round-trip.

```elixir
# ❌ N+1 QUERIES - Database hit for EACH user (1 + N queries)
users = Repo.all(User)

Enum.map(users, fn user ->
  user_with_posts = Repo.preload(user, :posts)  # Query for every iteration!
  %{name: user_with_posts.name, post_count: length(user_with_posts.posts)}
end)

# ✅ SINGLE QUERY - Preload in the query loads all at once (2 queries total)
import Ecto.Query

users =
  User
  |> preload(:posts)
  |> Repo.all()

Enum.map(users, fn user ->
  %{name: user.name, post_count: length(user.posts)}
end)
```

## Why this matters

**Performance impact**: With 100 users, the ❌ version executes **101 queries** (1 for users + 100 for posts). The ✅ version executes **2 queries** (1 for users + 1 for all posts).

**Database load**: N+1 queries create network round-trip overhead and database connection pressure under load.

## When to use each approach

**Query `preload`** (in the query pipeline):

- Loading associations for multiple records
- Building dashboards, lists, or index pages
- Any scenario where you're working with collections

**`Repo.preload/2`** (on individual structs):

- Loading associations for a single record after fetching
- Conditionally loading based on runtime logic
- Adding associations to structs you already have

```elixir
# Query preload - for collections
posts = Post |> preload([:author, :comments]) |> Repo.all()

# Repo.preload - for single records or conditional loading
post = Repo.get!(Post, id)
post = if include_author?, do: Repo.preload(post, :author), else: post
```

## Catching N+1 queries in development

Add a query logger to `config/dev.exs` to spot N+1 patterns:

```elixir
config :my_app, MyApp.Repo,
  log: :debug  # Shows all queries in the console
```

Watch for repeated similar queries - that's your N+1 indicator.

## Links

- [Ecto.Query.preload/3 docs](https://hexdocs.pm/ecto/Ecto.Query.html#preload/3)
- [Ecto.Repo.preload/3 docs](https://hexdocs.pm/ecto/Ecto.Repo.html#c:preload/3)


---

Created by: almirsarajcic
Date: November 26, 2025
URL: https://elixirdrops.net/d/NWta3KyP
