Solving N+1 Queries with DataLoaders
Batch and cache database lookups using dataloaders to eliminate N+1 query explosions in resolvers.
The N+1 Problem in GraphQL
GraphQL lets clients ask for nested data in a single request, like a list of posts and each post's author. The danger is hidden in the resolvers.
Suppose you fetch 100 posts with 1 query, then resolve each post's author by running one query per post. That is 1 + 100 = 101 queries — the classic N+1 problem.
- 1 query to load the list (the 1)
- N queries, one per item, to load a related field (the N)
At scale this destroys latency and hammers the database. DataLoaders are the standard fix.
Seeing N+1 in a Strawberry Resolver
Here is a naive Strawberry resolver that triggers N+1. Each author resolver issues its own database call.
If a query returns 50 posts, this author resolver fires 50 separate SELECT statements. The list query plus those 50 lookups is the N+1 explosion.
import strawberry
@strawberry.type
class Author:
id: int
name: str
@strawberry.type
class Post:
id: int
title: str
author_id: int
@strawberry.field
async def author(self) -> Author:
# BAD: one DB round-trip per post -> N+1
row = await db.fetch_one(
"SELECT id, name FROM authors WHERE id = :id",
{"id": self.author_id},
)
return Author(id=row["id"], name=row["name"])All lessons in this course
- Defining Types, Queries and Mutations
- Solving N+1 Queries with DataLoaders
- Real-Time GraphQL Subscriptions
- Query Cost Analysis and Depth Limiting