Skip to main content

N+1 Query Problem

Updated 3 min read

Share this page

Send the link, quote the definition with a link back, or show it as a card on your own site.

https://softwaredictionary.org/terms/n-plus-one-query

In short

The N+1 query problem is a performance bug where code runs one query to load a list and then one extra query per item, instead of fetching it all at once.

What is the N+1 query problem?

The N+1 query problem happens when code fetches a list of N records with one query and then loops over them, running a separate query for each record's related data. That makes 1 + N queries in total. With 10 records it is barely noticeable, but with 1,000 records a single page load sends 1,001 queries to the database.

The problem is often hidden by an ORM's lazy loading: reading post.author inside a loop looks like a simple property access, but it silently runs a query each time. Every individual query is small and fast, yet the network round trips and per-query overhead add up to a slow page. The fix is to fetch related data in a fixed, small number of queries, using eager loading in the ORM, a single JOIN, or one batched query with WHERE id IN (...). GraphQL servers commonly solve it with a batching layer, often called a data loader, that collects IDs and loads them together.

It is like going to the grocery store once for each item on your shopping list instead of buying everything in one trip. You can spot the problem in database query logs, ORM debug output, or request traces that show the same query shape repeated dozens of times per request, and some teams add tests that fail if an endpoint exceeds a set number of queries.

The N+1 problem is different from a slow query. A slow query is one expensive statement that an index or rewrite can often fix, while N+1 is many cheap statements that each look fine on their own, so adding indexes does not help. Eager loading everything is not always the answer either, because loading related data a page never uses wastes memory and time.

At a glance

Listing three posts with their authors. The N+1 way runs one query for the posts and then one more query per post for its author: four round trips to the database. The fixed way gets the posts and their authors together with a join, in a single query.N + 1 queries1 for the list, then 1 per postSELECT * FROM posts LIMIT 3SELECT * FROM users WHERE id = 1SELECT * FROM users WHERE id = 2SELECT * FROM users WHERE id = 34 round tripsOne queryposts and authors togetherSELECT posts.*, users.name FROM postsJOIN users ON users.id = posts.author_idLIMIT 31 round tripOften hidden in an ORM loop: for each post, post.author
With 3 posts it's 4 queries; with 1,000 posts it's 1,001. Fetching related rows together keeps it at one or two, however long the list.

Key takeaways

  • N+1 means one query for a list plus one query per item in that list.
  • ORM lazy loading is the most common hidden cause.
  • Each query is fast, but the round trips add up as the list grows.
  • Fix it with eager loading, a JOIN, or a batched IN query.
  • Indexes don't fix N+1, because the problem is the number of queries.

Example

N+1 queries and a batched fixjavascript
// N+1: 1 query for the posts, then 1 query per post for its author
const posts = await db.query("SELECT * FROM posts LIMIT 50");
for (const post of posts) {
  const rows = await db.query("SELECT * FROM users WHERE id = ?", [post.author_id]);
  post.author = rows[0];
}

// Fix: load all the authors in one extra query (2 queries in total)
const ids = posts.map((p) => p.author_id);
const authors = await db.query("SELECT * FROM users WHERE id IN (?)", [ids]);
const byId = new Map(authors.map((a) => [a.id, a]));
for (const post of posts) post.author = byId.get(post.author_id);

Readers ask

How do I detect N+1 queries?

Turn on query logging in your ORM or database and look for the same query repeated with different IDs during one request. Tracing and performance monitoring tools, and some ORM plugins, can flag the pattern automatically.

Does using an ORM cause the N+1 problem?

The ORM doesn't cause it by itself, but lazy loading makes it very easy to write by accident. Most ORMs provide eager loading options, such as include or prefetch, to load related records up front.

Is a JOIN always better than N+1 queries?

Usually, but not always. A join can duplicate parent data across many rows, so for large one-to-many relationships two queries, one for parents and one batched query for children, are often cleaner and just as fast.

See also

Spotted a mistake or something missing on this page?Suggest an edit

Read a random page
Open today's review
Switch to the dark theme
Read this page in Türkçe

More

Settings