Leonardo Correa
3 min readApr 11, 2020

--

Apollo server cache warm up technique

I have been working on transitioning two applications from REST to GraphQL for a Health Insurance company. One application is the members portal (web). The second is the react-native codebase. Apollo server resolvers offer special kind of challenges when it comes down to performance and caching. Here I am going to describe one of the techniques we used to make the overall request faster. You will not find this technique in any official documentation.

The problem

I noticed the Apollo server nested resolvers work sequentially. Imagine a timeline. from left to right. For example:

===> resolver 1 (5 secs)===
===== resolver 2 (4 secs)===

As you can see, the overall response time is 9 seconds. Let’s give resolvers some hypothetical names:

  • Resolver 1: MembershipResolver
  • Resolver 2: MembersResolver (nested resolver), list of members in a given membership.

Here is the sample query:

query {
membership {
id
state
members {
memberId
firstName
lastName
}
}
}

Solution

My solution was proactively fire off nested resolvers earlier so when Membership resolver executes nested Member resolver, the data will be ready in the Dataloader cache.

You need the following requirements for this technique to work:

  • Nested resolvers are loaded via Dataloader. Example: context.loaders.getMembers.load(membershipId)
  • Nester resolvers can be loaded independently or just need a resolved ID. In our case the “membershipId” is decoded from JWT token and attached to the Apollo context.
  • Your parent resolver knows when nested resolvers are eligible for a cache warm-up.
  • It does not replace your model caching strategy. You can still have them. If the data is cached, this technique won’t save any time. We actually cache some data at model level too.

I looked around the web and official Apollo docs and found nothing similar. So I call this technique:

Cache-warm-up-for-nested-resolver-within-a-request

The technique to solve the problem

The solution is perform a look-ahead on incoming query and fire off nested eligible resolvers at the begin of the parent resolver. Look at the example:

Parent resolver:

https://github.com/leonardoanalista/apollo-server-example-8d4bp/blob/master/resolvers.js#L6-L29

The warm-up cache:

https://github.com/leonardoanalista/apollo-server-example-8d4bp/blob/master/warm-up-cache.js

Note: function “warmUpCache” code can easily be extracted to work with any parent resolver.

With this technique we were able to significantly reduce the overall response time. In this example here, we are now able to get the response in 5 seconds now instead of 9 seconds (waterfall):

===> resolver 1 (5 secs)===
==> resolver 2 (4 secs)===

In my next post, I will write about the second improvement technique I used in this mission to implement Apollo and GraphQA at ahm.

Here is the full working sample code: https://codesandbox.io/s/apollo-server-example-8d4bp. You can execute queries, maybe comment out the line that executes the “warmUpCache” function and compare the response time.

https://codesandbox.io/s/apollo-server-example-8d4bp?fontsize=14&hidenavigation=1&module=%2Fresolvers.js&theme=dark

Key takeaways: There is nothing extraordinary about this technique. It isn’t difficult to implement at all. I would like to encourage you to think out of the box, go beyond the documentation and find creative or refine old ways to improve modern approaches. I don’t think you need to write machine learning or complex data structure to solve problems. Simplicity is the key.

Thanks for reading. If you have any question feel free to write in the comments.

Next post I’ll write about another interesting technique that saves a few seconds, also not documented (neither recommended on docs). Then finally, a third post about the approach and challenges to introduce GraphQL in an existing codebase, development experience and strategy to “sell” it to the business.

Leonardo Correa

--

--

Leonardo Correa

#Brazilian/Australian, #Frontend Dev, #JiuJitsu addicted, #SoccerPlayer, #WorldTraveller, #dad https://bjjnerd.vercel.app