We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Stop using `Repo.preload` in loops - use `preload` in queries
almirsarajcic
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.
# ❌ 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
# 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:
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
copied to clipboard
Comments (0)
Sign in with GitHub to join the discussion