N+1 Problem
The N+1 problem is when fetching a list of N items then fetching related data for each one results in 1 + N queries. One query for the list. N more queries to hydrate each item. From ECE459 L10.
Why?
It feels natural to write a loop: “get the list, then for each item, get its details.” That loop turns into a round-trip per item. Latency adds up on the wire, not in the code you see.
The L10 example
You want to email every customer with an unpaid invoice:
- Query 1: get customer IDs for all unpaid invoices
- For each of 500 invoices, query the customer’s email
Result: 501 queries when 1 or 2 would do.
Fixes:
- Single join query that returns emails directly
WHERE customer_id IN (...)— down to 2 queries- Eager loading: fetch related entities alongside the originals, even if you might not need them
Where it hides
- ORMs (Hibernate, Rails ActiveRecord) silently turn nested object access into separate queries. A
.author.namein a loop is N extra SELECTs- GraphQL resolvers let the caller pick arbitrary nested fields. The resolver often fires one query per parent row unless you batch
- REST endpoints that return thin objects and force the client to fan out
In practice. The Rust juniper_eager_loading crate models this explicitly with a HasOne<T> enum (Loaded / NotLoaded). You load users first, collect their country IDs, fetch those countries in one query, then stitch them back. Two queries instead of N+1.
Reference: The GraphQL DataLoader pattern visualized