query {
posts(first: 50) {
title
author { name }
}
}
The N+1 problem is one query for a list, then one extra query for each item in it. GraphQL causes it because it runs each field's resolver (the function that fetches that field) on its own.
Here, the posts resolver runs one query and gets 50 posts. Then the author resolver runs once per post. That makes 50 separate queries like SELECT * FROM users WHERE id = ?. The total is 1 + N queries. Deeper nesting makes it worse.
DataLoader fixes this. It batches and caches loads inside one request. It works like this:
- Each
authorresolver callsloader.load(authorId)instead of querying the database directly. - DataLoader collects all the IDs asked for in the same tick of the event loop.
- It calls your batch function once with the full list of IDs. The batch function runs one
WHERE id IN (...)query. - The batch function must return the results in the same order as the keys.
- If the same ID is asked for again, DataLoader returns it from its per-request cache.
Create a new loader for every request. This way, the cache does not leak data between users.
- Resolvers that run per field cause 1 + N database queries.
- DataLoader batches the loads from one tick into one query.
- The batch function must return results in the same order as the keys.
- The per-request cache removes duplicate IDs.
- Create a new loader for every request.
Read more