Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
25 Aug 2025 · 5 min read ·Article 56 / 125
Go

56 What Is a Subscription in GraphQL?

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

56 What Is a Subscription in GraphQL?

If you have ever built an application using GraphQL, you are most likely already familiar with its two main operations: query and mutation. However, many developers still don’t take full advantage of subscription, the third feature that enables real-time communication between the client and the server. In this article, I will take a deep dive into what a subscription in GraphQL is, why we need it, and how to implement subscriptions with code examples, a simple flow, and even a simulation so that you gain an end-to-end understanding.


Core Concepts: Query, Mutation, and Subscription

Before we go any further into subscriptions, let’s revisit the three root operations in GraphQL:

OperationPurposeExample
QueryFetch data (Read)Fetch a list of users
MutationModify data (Create/Update/Delete)Add a user
SubscriptionReceive data updates in real time (Listen)New user notification

Simply put, a query is stateless — the client asks, the server answers. A mutation is the same, except that it changes the server’s state. Subscription, on the other hand, is different: the client “subscribes” to certain changes and automatically receives data every time a relevant event occurs.


Defining Subscriptions in GraphQL

A subscription is a GraphQL operation that allows the client to receive data in real time whenever a particular event occurs on the server. Unlike queries and mutations, which use the HTTP request-response protocol, subscriptions typically use WebSockets to keep the connection between the client and the server open.

Using subscriptions, you can build features such as:

  • Real-time notifications (e.g., a new message/chat arrives)
  • Live product stock updates
  • Up-to-date user online status
  • Live transaction monitoring

Subscription Flow: How Does It Work?

Let’s look at the basic flow of a subscription in GraphQL through the following diagram:

MERMAID
sequenceDiagram
    participant Klien
    participant Server
    Note right of Klien: Membuka koneksi WebSocket
    Klien->>Server: SUBSCRIPTION `newMessage`
    Server--)Klien: Ack (Koneksi terbuka)

    Note left of Server: Ketika ada event baru
    Server-->>Klien: Push data pesan baru

    Klien->>Server: Unsubscribe (atau tutup koneksi)
    Server--)Klien: Koneksi ditutup
Flow explanation:

  1. The client opens a connection (usually a WebSocket) to the server.
  2. The client sends a subscription operation.
  3. While the connection is open, the server watches for the related events.
  4. When an event occurs (for example, a new message arrives), the server pushes the data to the client.
  5. The client can close the connection once it no longer needs updates.

Example Case: Chat Room Subscription

To make the concept clearer, let’s take a chat application as a case study. Suppose we want a feature where “new messages appear without having to reload the page.”

1. The GraphQL Subscription Schema

On the server side (for example, using Apollo Server):

javascript
 1const { gql } = require('apollo-server');
 2
 3const typeDefs = gql`
 4  type Message {
 5    id: ID!
 6    content: String!
 7    author: String!
 8    timestamp: String!
 9  }
10
11  type Query {
12    messages: [Message]
13  }
14  
15  type Mutation {
16    postMessage(content: String!, author:String!): Message
17  }
18
19  type Subscription {
20    messageAdded: Message
21  }
22`;

2. The Subscription Resolver

The next step is to make use of a pub/sub mechanism. In Node.js, you typically use graphql-subscriptions:

javascript
 1const { PubSub } = require('graphql-subscriptions');
 2const pubsub = new PubSub();
 3
 4const resolvers = {
 5  Query: {
 6    messages: () => getAllMessages(),
 7  },
 8  Mutation: {
 9    postMessage: (_, { content, author }) => {
10      const message = saveMessage({ content, author });
11      // publish event
12      pubsub.publish('MESSAGE_ADDED', { messageAdded: message });
13      return message;
14    }
15  },
16  Subscription: {
17    messageAdded: {
18      subscribe: () => pubsub.asyncIterator(['MESSAGE_ADDED'])
19    }
20  }
21};
Every time a postMessage occurs, the server publishes an event, ensuring that all subscribed clients receive the new data.

3. Client Code: Subscribing to the Event

For example, using Apollo Client (React):

javascript
 1import { useSubscription, gql } from '@apollo/client';
 2
 3const MESSAGE_ADDED = gql`
 4  subscription OnMessageAdded {
 5    messageAdded {
 6      id
 7      content
 8      author
 9      timestamp
10    }
11  }
12`;
13
14function Messages() {
15  const { data, loading } = useSubscription(MESSAGE_ADDED);
16
17  if (loading) return <p>Loading...</p>;
18  
19  return (
20    <ul>
21      {data.messageAdded.map(msg => (
22        <li key={msg.id}>{msg.author}: {msg.content}</li>
23      ))}
24    </ul>
25  );
26}
Whenever a new message arrives on the server, the new data is automatically pushed to this component without a reload.


Simulating Live Updates

To make things even clearer, here is a simple illustration using a table of time and subscription events:

TimeEventNotes
09:00Client A subscribesWebSocket connection opened
09:02Client B subscribesSecond connection opened
09:03Client C postMessageServer publishes the event
09:04Clients A and B receiveMessage data pushed in real time
09:05Client A unsubscribesClient A no longer receives updates
09:06Client C postMessageOnly Client B receives the update

Challenges and Best Practices

Subscriptions are very powerful, but there are a few challenges:

  1. Scaling:

    • Keep-alive connections require more resources than request-response.
    • Use a scalable WebSocket server (for example, Redis as a pub/sub backend).
  2. Authentication:

    • Make sure the authentication process still runs for every “subscribe” connection.
    • Implement forbidden handling in real time.
  3. Resource cleanup:

    • Don’t forget to handle disconnects; otherwise, memory leaks can happen very easily.
  4. Fallback:

    • Sometimes WebSocket connections are not supported in certain environments. Provide a fallback (e.g., polling).

When Should You Use Subscriptions?

Use CaseQuery/MutationSubscription
Static data (profile)
Periodic list updates
Instant notifications
Chat
Stock price updates

Use subscriptions when you need a real-time trigger. For data that rarely changes, queries/mutations are more efficient.


Conclusion

GraphQL subscriptions are a powerful tool for bringing a real-time experience to your modern applications, from chat and monitoring to notification systems. By knowing when to use them and how to implement them, you will feel more confident building applications that are immersive and responsive.

I hope this article helps deepen your understanding, and don’t hesitate to experiment with GraphQL subscriptions in your next project!


References:

Related Articles

💬 Comments