GraphQL Cache Updates Made Easy

Share on facebook
Share on google
Share on twitter
Share on linkedin

Apollo Graphql comes with built-in support for caching which can be used as a state management system (which they recommend). There are a couple of different ways to update cache after an update in this state management system:

  • Refetch query
  • Built-in normalization
  • Update callback

This post will teach you when and how to do the different kinds of cache update strategies and show you some util functions to make cache updates as easy as a one-liner.

Refetch query

After executing a mutation and changing something on the server, chances are you’re going to need to refresh the UI. And a quick solution is to use the refetchQueries API.

For example: With refreshQueries you specify one or more queries in order to refresh the parts that have been affected by the mutation.

For example:

While this works, it has a big disadvantage attached to it, in that we need to make multiple network trips to render our UI. This extra round trip also occurs even if we have the data on the client.

Built-in normalisation

The Apollo Client is an abstraction on top of normalized data and cache and this facade provides access to the underlying data. This is similar to how databases handle access to data. This storage facade can intercept queries and automatically remove duplication. It can also update the cache automatically, though this depends on the type of mutation.

When dealing with any type of data that needs to be stored somewhere, we need to keep the amount of duplicate data saved to an absolute minimum. Ideally, the goal here is no duplicate data.

This facade provides an API layer that is much easier to use. The API’s allow us to:

  • Configure/design the client-side data using cache policies.
  • Query data using client.readQuery or client.watchQuery.
  • Mutate data using useMutation.

The Apollo Client provides a set of tools to interact with the cached data and all of this comes out of the box and ready to use. By minimizing direct access to the actual data using the facade/API enables data normalization, behind the scenes.

How the Apollo Client normalises data is:

  • By splitting the results into individual objects.
  • Assign a logically unique identifier to each object, so the cache is able to keep track of the object.
  • Storing objects in a flattened structure.

You can learn more about how GraphQL does normalization here.

Update callback

When we perform an add, remove or reorder items that are cached, the Apollo Client is not able to automatically update the cache. We need to write an update function to instruct the cache on how we want to update it.

There are some rules that we can follow so we know when we need to create our own update function. These rules are as follows:

  • If the side-effect we want to occur has nothing to do with the return data.
  • We can’t return the entire set of changed objects.
  • The mutation changes the ordering.
  • The mutation adds or removes items.

A side-effect would be to clear the cache after a mutation, for example logging out of a system. We get a successful response from the mutation, but we don’t need to cache anything. For this we can use the client.clearStore() method in the update function.

We need to return the entire list of objects that were changed for the automatic update to work (using the normalization).

To update the cache if we cannot return the entire set, we use the update function:

To remove an item from the cache filter out the deleted item.

Notice how we first remove the entity from the query and then from the normalized cache using evict.

To add an item to the cache, get the existing entities from the readQuery and use the spread operator ([…]) to append the new course to the objects in cache.

Now we know what we need to do and how to do it, let’s see how we can make it simpler to do these cache updates.

Making Cache Updates Easy

As you saw in the previous section, doing the manual updates can be quite tedious. For that reason, I have created some utils for doing these updates as a one-liner.

First we define an interface with an id, as this is the convention we will be using to know the property to get the entity’s id from.

From here we can create a function to handle adding new items to the cache.

This will read the query and add the new entity to the cache.

And the same for deleting:

This will read the query and remove the entity from the cache.

These helpers can be used like this:


In this post, we learned about the various ways that the Apollo Client handles updates to the cache. We looked at how the Apollo Client handles automatic cache updates using normalization, refetch queries, and manual updates of the cahce.

We finished off by showing you how to simplify the manual update process by creating a function to handle the update and deletes, so these become an easy-to-use one line of code.

Do you want to become an Angular architect? Check out Angular Architect Accelerator.

Related Posts and Comments

How I migrated my Course Platform to Analog (step by step)

Analog is a full-stack framework for Angular ala NextJS that offers server-side rendering, static site generation, and API routes. Analog empowers Angular with server rendering tools making it optimal for public websites. Otherwise, Angular has often been neglected in favor of NextJS/NuxtJS for these purposes (due to the subpar SSR/SSG experience). I recently migrated my

Read More »

The Future of Angular and the Latest Features in Angular

In this video, I’ll be discussing the future of Angular and the latest features in Angular 17, including standalone components, signals, new control flow, the deferred operator, and server-side rendering improvements. I’ll also touch on the use of Tailwind CSS for styling and the benefits it offers. Join me to learn more about the exciting

Read More »

How to Invest as a Software Developer

In this video, I share my personal investment strategy as a software developer, focusing on putting money to work and owning assets that generate cash flow and appreciation. I discuss the snowball effect of building an investment portfolio over time and the importance of compounding. I also touch on the allocation of investments in stocks,

Read More »

Angular 17: What’s new?

Angular has since the latest major version started what the Angular team calls a renaissance, which means a radical renewal of the framework. The main goals of the latest updates have been to improve the developer experience and performance so it aligns more with the other leading front-end frameworks in the space by introducing new

Read More »

How to Set up a CI pipeline with Azure Pipelines and Nx

It goes without saying that having a CI pipeline for your Angular apps is a must. Setting one up for regular Angular apps is fairly straightforward but when you have an Nx monorepo there are certain other challenges that you have to overcome to successfully orchestrate a “build once, deploy many” pipeline. This post will

Read More »