DataLoader for batching in GraphQL - Time & Space Complexity
When using DataLoader for batching in GraphQL, we want to understand how the number of database calls changes as we request more data.
We ask: How does batching affect the total work done when fetching many items?
Analyze the time complexity of this DataLoader batch function.
const userLoader = new DataLoader(async (userIds) => {
const users = await db.users.findMany({
where: { id: { in: userIds } }
});
const userMap = new Map(users.map(user => [user.id, user]));
return userIds.map(id => userMap.get(id));
});
// Later in resolvers:
const user1 = await userLoader.load(1);
const user2 = await userLoader.load(2);
This code batches multiple user ID requests into one database query.
Look for repeated work inside the batch function.
- Primary operation: One database query fetching all requested users at once.
- How many times: Once per batch of user IDs, not once per user ID.
As the number of user IDs requested grows, the database query fetches all at once.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 1 database query fetching 10 users |
| 100 | 1 database query fetching 100 users |
| 1000 | 1 database query fetching 1000 users |
Pattern observation: The number of database queries stays the same (one per batch), but the query size grows with n.
Time Complexity: O(n)
This means the work grows linearly with the number of user IDs requested, but the number of database calls stays minimal.
[X] Wrong: "DataLoader makes each user request a separate database call."
[OK] Correct: DataLoader batches all requests in a short time window into one query, reducing calls significantly.
Understanding how batching reduces repeated work is a valuable skill that shows you can write efficient data fetching logic in real projects.
What if the batch function made separate database calls for each user ID instead of one query? How would the time complexity change?
Practice
DataLoader in GraphQL?Solution
Step 1: Understand DataLoader's role
DataLoader groups multiple data requests into batches to reduce the number of database calls.Step 2: Recognize performance benefits
By batching and caching, DataLoader improves performance and avoids redundant fetching.Final Answer:
To batch and cache database requests to improve performance -> Option AQuick Check:
DataLoader batches and caches = C [OK]
- Thinking DataLoader creates database tables
- Confusing DataLoader with schema validation tools
- Assuming DataLoader generates test data
Solution
Step 1: Recall DataLoader instantiation syntax
DataLoader is a class and must be instantiated with thenewkeyword.Step 2: Check the correct method call
The constructor takes a batch loading function as argument, sonew DataLoader(batchLoadFn)is correct.Final Answer:
const loader = new DataLoader(batchLoadFn); -> Option AQuick Check:
Usenew DataLoader()to create instance [OK]
- Omitting 'new' keyword
- Using incorrect method calls like .new or .load
- Calling DataLoader as a regular function
const batchLoadFn = async (keys) => {
return keys.map(key => key * 2);
};
const loader = new DataLoader(batchLoadFn);
(async () => {
const result = await Promise.all([
loader.load(1),
loader.load(2),
loader.load(3)
]);
console.log(result);
})();What will be printed in the console?
Solution
Step 1: Understand batchLoadFn behavior
The function takes an array of keys and returns an array where each key is multiplied by 2.Step 2: Analyze loader.load calls
Calling loader.load(1), loader.load(2), loader.load(3) batches keys [1,2,3] and returns [2,4,6].Final Answer:
[2, 4, 6] -> Option BQuick Check:
Keys doubled = [2,4,6] [OK]
- Expecting original keys instead of doubled values
- Thinking batchLoadFn returns undefined
- Assuming batchLoadFn must reject Promise
const batchLoadFn = (keys) => {
keys.forEach(key => console.log(key));
};
const loader = new DataLoader(batchLoadFn);
loader.load(1).then(console.log);What is the main problem with this code?
Solution
Step 1: Check batchLoadFn return value
batchLoadFn must return a Promise resolving to an array of results matching keys.Step 2: Identify missing return
Current batchLoadFn only logs keys and returns undefined, causing DataLoader to fail.Final Answer:
batchLoadFn does not return a Promise resolving to an array -> Option DQuick Check:
Batch function must return Promise with results [OK]
- Thinking logging inside batchLoadFn causes error
- Believing loader.load requires array argument
- Assuming forEach is disallowed in batchLoadFn
Solution
Step 1: Understand DataLoader result order requirement
DataLoader expects the batch function to return an array matching the input keys order, including nulls for missing data.Step 2: Handle nulls properly
Returning nulls in place preserves the order and allows DataLoader to cache results correctly without errors.Final Answer:
Return an array with nulls in the same order as input keys -> Option CQuick Check:
Keep result array order with nulls for missing keys [OK]
- Filtering out nulls breaks result order
- Throwing errors for missing data unnecessarily
- Returning empty array causes cache issues
Ready to prove it?
Pass the test and this pattern moves unknown
