tagged by: GraphQL

2020-10-08
Efficient DTOs

When we need to return data to be displayed on the UI as DTOs we are going to read from multiple repositories unless for trivial UI. For example forum posts can have author (a user) and comments. Comments can have author too.

{
      posts: [{
        title: "Efficent DTO",
        author: {
          name: "Marco"
        },
        comments: [{
          author: {
            ...
    }
    

In this context, no matter the technology we are going to use, the N+1 problem will pop up. For instance with:

  • ReST API: we execute a request for the list of posts then N requests for the User resources.
  • ReST API + hint, like /posts?with=user: now we have only one ReST request but probably on the server users are loaded one by one from their repository.
  • GraphQL: without data loaders you still have the same problem, the user of a post is resolved for each post.

The last example is not accidentally: when I faced this problem I thought at first to resort to GraphQL and this is why my idea comes from it. However I did not have dynamic queries but static ones, read "several endpoints that return always the same JSON", hence I did not want to adopt en engine to parse, for a given endpoint, the same query over and over again.

I found that what I needed were batched loaders and data loaders, something that every GraphQL implementation have as associated library. In our example for every post DTO resolution the load of the user is delayed until we have the complete list of the users to load (same for comments and users of comments) so we can batch load users.
Other sulutions, illustrated below, do not scale, at least in my use cases.
The library that implements the above algorithm, without GraphQL, is graph-loader.