Skip to content

Guide · Open source

How to use DataLoader: batching and caching in Node.js

Updated · written with AI from the project's own documentation and checked against our catalogue data

DataLoader is a small JavaScript utility for Node.js that sits in your data-fetching layer. It lets your code load items one at a time while DataLoader groups those calls into batches and caches results for a single request. This guide shows you how to install it, write a batch function, and use its per-request cache so you make fewer round-trips to your backend.

DataLoadergraphql/dataloader · ★ 13.4k · MIT

Quick start

  1. 1Install the package. Run npm install --save dataloader in your Node.js project.
  2. 2Write a batch function. Write a function that takes an Array of keys and returns a Promise resolving to an Array of values of the same length, in the same order.
  3. 3Create the loader. Pass the batch function to new DataLoader to create a loader instance.
  4. 4Call load with single keys. Call .load(key) for each item you need; DataLoader groups calls made in the same tick into one batch.
  5. 5Create loaders per request. Instantiate new loaders when each request starts so the in-memory cache stays scoped to that request.
  6. 6Optionally customise scheduling. Pass batchScheduleFn in the options if you need a custom timing window or manual dispatch.

Install DataLoader with npm

DataLoader is installed as a package with npm. Run the command below in your Node.js project.

DataLoader assumes a JavaScript environment with global ES6 Promise and Map classes. The README says these are available in all supported versions of Node.js, but it does not state an exact Node.js version.

npm install --save dataloader

Create a loader with a batch function

Each DataLoader instance is created with a batch loading function. This function accepts an Array of keys and returns a Promise that resolves to an Array of values. Each DataLoader instance represents a unique cache.

The batch function must return an Array the same length as the keys, with each index matching the same index in the keys. If a value is missing, return an Error instance or null for that position. The README example reorders results to match the requested keys and fills gaps with null or new Error().

  • The returned Array must be the same length as the keys Array.
  • Each index in the returned Array must correspond to the same index in the keys Array.
  • Missing results can be returned as null or as an Error instance.
const DataLoader = require('dataloader'); const userLoader = new DataLoader(keys => myBatchGetUsers(keys));

Load individual items and let batching happen

Call .load() with a single key. DataLoader coalesces all individual loads that occur within a single frame of execution (a single tick of the event loop) and then calls your batch function once with all requested keys. Your code can stay simple and still avoid many separate backend calls.

The README gives an example where a naive application might issue four round-trips, but with DataLoader it makes at most two.

const user = await userLoader.load(1); const invitedBy = await userLoader.load(user.invitedByID);

Change when batches are sent with batchScheduleFn

By default, batches are dispatched within the same tick of the event loop, which adds no extra latency. If you want a different timing, pass a custom batch scheduler as batchScheduleFn in the options. It receives a callback and should call that callback in the immediate future.

The README example below collects requests over a 100ms window, which adds 100ms of latency. Use this only if that trade-off suits your app.

const myLoader = new DataLoader(myBatchFn, { batchScheduleFn: callback => setTimeout(callback, 100), });

Use the per-request cache safely

After .load() is called once with a given key, the result is cached for the life of that loader. This removes repeated loads within one request. Create a new DataLoader instance when each request begins and drop it when the request ends, so that one user's cached data is never shown to another.

DataLoader's cache does not replace Redis, Memcache, or any other shared application-level cache. Subsequent calls with the same key do not include that key in the batch, but the returned Promise still waits for the current batch to finish.

  • Create loaders per request, for example inside an express route handler.
  • Do not reuse one loader across users whose data may differ.
  • For a cache shared between requests, use a separate tool such as Redis or Memcache.
function createLoaders(authToken) { return { users: new DataLoader(ids => genUsers(authToken, ids)), }; }

What people use it for

  • Loading users by ID while resolving nested fields in a GraphQL server built on graphql-js.
  • Reducing database round-trips when many related records are requested in the same request.
  • Avoiding repeated lookups of the same record within one web request without adding Redis.
  • Manually dispatching batches in tests or specialised code paths using a custom batchScheduleFn.

Frequently asked questions

Is DataLoader free to use?

DataLoader is released under the MIT licence, as listed for the graphql/dataloader project. Check the licence file in the repository for the full terms before using it in a commercial product.

What do I need to run DataLoader?

You need Node.js and an environment with global ES6 Promise and Map classes. The README does not state an exact Node.js version, so check the project's documentation for that detail.

How do I install DataLoader?

Run npm install --save dataloader in your project directory. This is the install method given in the README.

Does DataLoader replace Redis?

No. The README says DataLoader's caching does not replace Redis, Memcache, or other shared caches. Its cache only prevents repeated loads within a single request.

Can I use DataLoader outside GraphQL?

Yes. The README says it is useful in other situations as well, though it is often used when building a graphql-js service. It is for JavaScript and Node.js, and the README does not provide ports to other languages.

Why are my loader results mixed up between users?

The README warns against reusing a DataLoader instance across different users because cached data could appear in the wrong request. Create new loaders when each request begins and stop using them when it ends.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

DataLoader suits Node.js developers, especially those building GraphQL servers with graphql-js, who load many related records and want fewer backend calls with a per-request cache. It is less useful for simple apps making one or two data calls, or for projects that need a shared cache across requests, where Redis or Memcache is the better fit.

Install options & downloads