DEV Community

Mohammed Rabeeh
Mohammed Rabeeh

Posted on

Persisting DataLoader between requests and using it as a cache

I'm working on a project where I use the DataLoader to batch requests (N + 1 Problem). I accidentally created DataLoader beforehand and started to pass it in the context, instead of initializing the DataLoader in the context. I'll explain.

DataLoader is meant to be used for "per request batching and caching". Therefore, you would do something like this to implement DataLoader normally.

// app.js

app.register(..., {
  schema: ...
  context: () => {
    return {
      userLoader: new DataLoader(batchFunction);
    };
  },
});

Enter fullscreen mode Exit fullscreen mode

This would make it so that the DataLoader exist only in the context of a particular request. However, what I accidentally did was this:

// app.js

userLoader = new DataLoader(batchFunction);

app.register(..., {
  schema: ...
  context: () => {
    return {
      userLoader
    };
  },
});

Enter fullscreen mode Exit fullscreen mode

This started to cache the data between requests. It was not hitting my database for the data it already had. So I started wondering if there was anything wrong in caching the data in this way. I get batching. I get caching without having to manually implement it. I can clear the data->id from the cache when the database is updated. So far so good.

But there has to be issues with this implementation. One limitation I found is that as the cache grows, eventually the entire database will be cached. I don't know if that's an issue or not. This can be avoided by using { cache:false } option in the loader to cache only the required data.

It would be great if someone more experienced could give me some feedback and shed some more light on this. Thank you!

Top comments (3)

Collapse
 
danielrearden profile image
Daniel Rearden

Extensive conversation on this topic can be found in this issue in the repo. The TL;DR is that DataLoader is a way of batching requests and even though it uses a cache to help do this batching, it should not be as an application-level cache. The reasons for this are two fold -- one, there are unintended consequences (like issues when you start horizontally scaling your application); and two, lack of customization around how the cache behaves (for example, TTL). If you need an application-level cache, use the right tool for the job (for example, Redis).

Collapse
 
rabeehrz profile image
Mohammed Rabeeh

I haven't thought about the scaling issues. Makes a lot of sense. Thank you so much!

Collapse
 
bfunc profile image
Pavel Litkin

Can you elaborate a bit more about issues when you start horizontally scaling application please?