N+1 Query Problem
Also known as: N+1 select, N+1 problem
The N+1 query problem is issuing one query to fetch a list of N rows and then one additional query per row to fetch related data — N+1 round trips where a join or a batched IN clause would need one or two. Latency scales with result-set size, so it passes review with 10 rows and collapses at 1,000.
Last reviewed · Part of the Architecture Glossary
In practice
orders = Order.objects.filter(status="open") # 1 query
for o in orders:
print(o.customer.name) # 1 query each → NThe cost is round trips, not database work. At 0.4 ms per in-datacentre round trip, 500 orders is 200 ms of pure network — invisible on a laptop against localhost, obvious in production. Cross-AZ or against a proxy, multiply by three.
Fixes by layer:
- ORM:
select_related/prefetch_related(Django),JOIN FETCH(JPA),includes(Rails),Include(EF Core). - GraphQL: DataLoader — batch per tick and dedupe by key. GraphQL makes N+1 the default outcome of a nested resolver, which is why every mature server ships a loader.
- Detection: assert on query count in tests (
django-assert-num-queries, Bullet,n_plus_one_control). A count assertion catches the regression the day it is introduced; APM catches it a quarter later.
When it matters
Any list endpoint with nested data, any GraphQL schema with relations, any serialiser that touches a lazy attribute.
Common mistake
Fixing it with a cache. The cache hides the round trips until an invalidation or a cold start, at which point the original 500-query page returns — now during the worst possible traffic conditions.
See also
- Connection PoolA connection pool keeps a fixed set of open database connections and lends them to requests, avoiding per-request handshake cost and bounding concurrency at the database.
- Tail LatencyTail latency is the response time of the slowest requests — typically p99 and beyond.
- Little's LawLittle's Law states that the average number of items in a stable system equals the average arrival rate times the average time each item spends there: L = λW.