I'm always excited to take on new projects and collaborate with innovative minds.

Address

Kayseri, Turkey

Social

🚀 How GraphQL Cache and Subscriptions Work (and How They Differ from RESTful APIs)

GraphQL offers a powerful alternative to REST APIs in modern web applications. In this post, you’ll discover how caching and subscriptions work in GraphQL: how data is kept in the cache and how real-time updates are delivered over WebSocket.

🚀 How GraphQL Cache and Subscriptions Work (and How They Differ from RESTful APIs)

🚀 How GraphQL Cache and Subscriptions Work (and How They Differ from RESTful APIs)

As frontend developers, we usually talk to APIs through a REST structure. But in modern apps, when you need more dynamic, real-time and flexible data flow, GraphQL steps into the spotlight.

In this post, I’ll walk you through how cache and subscriptions work in GraphQL,
how they differ from RESTful APIs, step by step with examples from my own experience.


🔹 What Is GraphQL?

GraphQL is an API query language developed by Facebook.
Unlike REST, the client (frontend) queries only the fields it needs.
In other words, the frontend gets what it asks for, not whatever the backend decides to send (backend bro, mind your own business xD ).

🧠 A Quick Comparison

REST:

GET /users/1
{
  "id": 1,
  "name": "Ahmet",
  "email": "[email protected]",
  "posts": [
    { "id": 101, "title": "React Eğitimi" },
    { "id": 102, "title": "Next.js Rehberi" }
  ]
}

GraphQL:

query {
  user(id: 1) {
    name
    posts {
      title
    }
  }
}

Result:

{
  "data": {
    "user": {
      "name": "Ahmet",
      "posts": [
        { "title": "React Eğitimi" },
        { "title": "Next.js Rehberi" }
      ]
    }
  }
}

⚙️ GraphQL Basics

GraphQL is built on three core operation types:

TypeDescriptionExample
QueryReading dataquery { users { id name } }
MutationCreating/updating datamutation { createUser(name: "Ahmet") { id } }
SubscriptionReal-time datasubscription { newUser { id name } }

🧩 What Is GraphQL Cache?

In GraphQL, caching is handled by libraries like Apollo Client.
Instead of being “URL-based” like in REST, it works based on data type + id.

Example:

query {
  users {
    id
    name
  }
}

Response:

{
  "data": {
    "users": [
      { "id": "1", "name": "Ahmet" },
      { "id": "2", "name": "Mehmet" }
    ]
  }
}

Apollo Client stores this data in memory like this:

{
  User: {
    "1": { id: "1", name: "Ahmet" },
    "2": { id: "2", name: "Mehmet" }
  }
}

So when the same user data shows up again in a different query,
Apollo Client serves it from the cache instead of fetching it again.
Plus, unlike with a RESTful API, we don’t have to go set up a 
WebSocket just to fetch the data again + no extra library needed.


💾 Apollo Client Cache Policies

In GraphQL, the cache policy is set with fetchPolicy:

fetchPolicyDescription
cache-firstServe from cache if available, otherwise fetch from the server
network-onlyAlways fetch from the server
cache-onlyRead from the cache only
cache-and-networkShow the cache first, then fetch the latest data

Example usage:

useQuery(GET_USERS, {
  fetchPolicy: "cache-first",
});

⚡ What Is a Subscription?

Subscriptions are GraphQL’s biggest difference from REST.
They enable real-time data communication — just like the WebSocket approach.

In REST:

  • The client doesn’t know when data changes.
  • To get new data, you have to send requests like GET /messages over and over again (polling).

In GraphQL:

  • You “subscribe” once,
  • And whenever something changes on the server (for example, a new message arrives),
    it sends a notification instantly.

Example:

subscription {
  newMessage {
    id
    text
    sender {
      name
    }
  }
}

🔄 How Do Cache and Subscriptions Work Together?

This is where the magic of GraphQL begins ✨
Data coming from a subscription is automatically written to the cache by Apollo Client.
That means your UI component displays the new data automatically.

Example Flow:

  1. query { users { id name } } → users are saved to the cache
  2. subscription { newUser { id name } } → when a new user arrives
  3. Apollo adds it to the cache
  4. The UI component updates automatically (no manual state needed)

💻 React Example (Apollo Client)

import { gql, useQuery, useSubscription } from "@apollo/client";

const GET_USERS = gql`
  query {
    users {
      id
      name
    }
  }
`;

const NEW_USER_SUB = gql`
  subscription {
    newUser {
      id
      name
    }
  }
`;

export default function Users() {
  const { data, loading } = useQuery(GET_USERS);

  useSubscription(NEW_USER_SUB, {
    onData: ({ client, data }) => {
      const newUser = data.data.newUser;
      client.cache.modify({
        fields: {
          users(existingUsers = []) {
            const newUserRef = client.cache.writeFragment({
              data: newUser,
              fragment: gql`
                fragment NewUser on User {
                  id
                  name
                }
              `,
            });
            return [...existingUsers, newUserRef];
          },
        },
      });
    },
  });

  if (loading) return <p>Yükleniyor...</p>;

  return (
    <ul>
      {data.users.map((u) => (
        <li key={u.id}>{u.name}</li>
      ))}
    </ul>
  );
}

In this code:

  • useQuery() fetches the initial data
  • useSubscription() listens for new users
  • When new data arrives, Apollo adds it to the cache
  • The React component re-renders automatically 🔁

🔍 REST vs GraphQL Comparison

FeatureRESTGraphQL
Endpoint structureMultiple (/users, /posts)Single (/graphql)
Cache systemURL-based (HTTP)Type + ID based (Apollo Cache)
Real-time dataNoYes (Subscription)
Over-fetching riskHighNone
Data updatesManualAutomatic cache sync

🧠 Summary

  • Cache: Apollo Client stores data in memory based on type + id.
  • Subscription: Receives real-time data over WebSocket.
  • Together: Incoming data is automatically added to the cache, and the UI updates instantly.

This way:
✅ You don’t send extra API requests
✅ State management gets simpler
✅ You deliver a real-time user experience


✍️ Final Worddd!

Even though GraphQL may look more complex than REST,
with its cache and subscription features it lets you build
faster, more efficient and real-time apps in the modern frontend world.

Now you can build real-time systems that update data “without refreshing the page,”
unlike in REST — here’s to putting it to good use. ⚡

Author Ahmet Yüceler

I build web and mobile products with 6+ years of experience. I share what I learn here.

Get in touch →

Leave a comment

Your email address will not be published. Required fields are marked *