56 What Is a Subscription in GraphQL?
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:
| Operation | Purpose | Example |
|---|---|---|
| Query | Fetch data (Read) | Fetch a list of users |
| Mutation | Modify data (Create/Update/Delete) | Add a user |
| Subscription | Receive 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:
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
- The client opens a connection (usually a WebSocket) to the server.
- The client sends a
subscriptionoperation. - While the connection is open, the server watches for the related events.
- When an event occurs (for example, a new message arrives), the server pushes the data to the client.
- 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):
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:
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};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):
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}Simulating Live Updates
To make things even clearer, here is a simple illustration using a table of time and subscription events:
| Time | Event | Notes |
|---|---|---|
| 09:00 | Client A subscribes | WebSocket connection opened |
| 09:02 | Client B subscribes | Second connection opened |
| 09:03 | Client C postMessage | Server publishes the event |
| 09:04 | Clients A and B receive | Message data pushed in real time |
| 09:05 | Client A unsubscribes | Client A no longer receives updates |
| 09:06 | Client C postMessage | Only Client B receives the update |
Challenges and Best Practices
Subscriptions are very powerful, but there are a few challenges:
Scaling:
- Keep-alive connections require more resources than request-response.
- Use a scalable WebSocket server (for example, Redis as a pub/sub backend).
Authentication:
- Make sure the authentication process still runs for every “subscribe” connection.
- Implement forbidden handling in real time.
Resource cleanup:
- Don’t forget to handle disconnects; otherwise, memory leaks can happen very easily.
Fallback:
- Sometimes WebSocket connections are not supported in certain environments. Provide a fallback (e.g., polling).
When Should You Use Subscriptions?
| Use Case | Query/Mutation | Subscription |
|---|---|---|
| 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: