GraphQL
Beginner
1 min read
The N+1 Problem and DataLoader
Example
// npm install dataloader
import DataLoader from 'dataloader';
// Batch function: receives array of IDs, returns array of users in same order
async function batchLoadUsers(ids) {
const users = await db.users.findAll({ where: { id: ids } });
// Must return results in the SAME ORDER as ids
const userMap = Object.fromEntries(users.map(u => [u.id, u]));
return ids.map(id => userMap[id] ?? new Error(`User ${id} not found`));
}
// Create a DataLoader per request (never share across requests!)
function createLoaders() {
return {
user: new DataLoader(batchLoadUsers),
// Add more loaders as needed
postsByUser: new DataLoader(async (userIds) => {
const posts = await db.posts.findAll({ where: { authorId: userIds } });
return userIds.map(uid => posts.filter(p => p.authorId === uid));
}),
};
}
// Pass loaders via context in Apollo Server
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({
currentUser: authenticate(req),
loaders: createLoaders(), // fresh loaders per request
db,
}),
});
// In resolver — DataLoader batches automatically
const resolvers = {
Post: {
author: (post, _, { loaders }) => loaders.user.load(post.authorId),
// 100 posts → 1 DB query instead of 100
},
};
Related Resources
GraphQL Reference
Complete tag & property list
GraphQL How-To Guides
Step-by-step practical guides
GraphQL Exercises
Practice what you've learned
More in GraphQL