0
0
GraphQLquery~5 mins

DataLoader batching and caching in GraphQL

Choose your learning style9 modes available
Introduction

DataLoader helps to group many small data requests into fewer big ones and remembers past requests to avoid asking the same thing twice.

When your app needs to get data about many users at once, like showing a list of friends.
When you want to avoid asking the database multiple times for the same data during one request.
When you want to speed up your app by reducing repeated data fetching.
When your GraphQL server resolves fields that require loading related data from a database.
When you want to keep your code clean by handling data fetching efficiently in one place.
Syntax
GraphQL
const DataLoader = require('dataloader');

const loader = new DataLoader(async (keys) => {
  // keys is an array of IDs
  // Return an array of results in the same order
});

// Use loader.load(key) to get data for one key
// Use loader.loadMany([key1, key2]) to get data for many keys

The function passed to DataLoader receives an array of keys and must return a Promise of an array of results in the same order.

DataLoader caches results during one request to avoid duplicate fetching.

Examples
This example batches user ID requests and returns users in the same order as requested.
GraphQL
const userLoader = new DataLoader(async (userIds) => {
  const users = await db.getUsersByIds(userIds);
  return userIds.map(id => users.find(user => user.id === id));
});
This batches post ID requests similarly, improving efficiency.
GraphQL
const postLoader = new DataLoader(async (postIds) => {
  const posts = await db.getPostsByIds(postIds);
  return postIds.map(id => posts.find(post => post.id === id));
});
Sample Program

This program creates a DataLoader to batch user ID requests. It fetches users with IDs 1, 2, and 3 efficiently and prints their data.

GraphQL
const DataLoader = require('dataloader');

// Fake database function
async function getUsersByIds(ids) {
  const allUsers = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
    { id: 3, name: 'Charlie' }
  ];
  // Simulate async DB call
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(allUsers.filter(user => ids.includes(user.id)));
    }, 100);
  });
}

// Create DataLoader instance
const userLoader = new DataLoader(async (userIds) => {
  const users = await getUsersByIds(userIds);
  return userIds.map(id => users.find(user => user.id === id));
});

// Use DataLoader to load users
async function main() {
  const user1 = await userLoader.load(1);
  const user2 = await userLoader.load(2);
  const user3 = await userLoader.load(3);
  console.log(user1);
  console.log(user2);
  console.log(user3);
}

main();
OutputSuccess
Important Notes

DataLoader batches requests that happen in the same tick of the event loop.

Cache is per DataLoader instance and usually per request to avoid stale data.

Always return results in the same order as the keys array to avoid mismatches.

Summary

DataLoader groups many small data requests into fewer big ones to improve speed.

It remembers past requests during one operation to avoid asking the same data twice.

Use it in GraphQL servers to efficiently load related data like users or posts.