02 / 03

How is caching handled in GraphQL?

Unlike traditional REST APIs, where every resource has its own unique URL (e.g., /api/users/1), GraphQL typically uses a single endpoint (usually /graphql) and relies on POST requests. Because HTTP clients and Content Delivery Networks (CDNs) see the exact same URL for every request, standard HTTP caching doesn't work out of the box. To solve this, the GraphQL ecosystem handles caching in two primary ways: Client-side (Normalized) Caching and Server-side Caching.

Client-Side Caching (Normalized Cache), Popular GraphQL clients like Apollo Client and Urql solve the caching problem by implementing an intelligent client-side cache. Instead of caching the entire HTTP response, they break the data down using normalization.

How Normalization Works:
  1. 1

    Flattening the data: The client takes the nested JSON response from a query and splits it into individual objects.

  2. 2

    Generating unique IDs: It assigns a unique identifier to each object (typically combining the object's __typename and id, e.g., User:1).

  3. 3

    Storing in a key-value map: It saves these objects in a flat lookup table.

  4. 4

    If Query A fetches User 1's name, and Query B later fetches User 1's email, the client merges this data into the same cache entry (User:1). If any query updates User 1, every component on your UI using that user's data updates automatically.

Server-Side Caching: When you need to cache data on the server to protect your database or speed up response times, you generally use three approaches
  1. 1

    Graph-Level Caching (Persisted Queries)

  2. 2

    Cache Control Directives

  3. 3

    Resolver-Level Caching (Data Loader)