Subscriptions Overview: Real-Time GraphQL and Pub/Sub
Learn how to implement real-time data updates in your API using GraphQL Subscriptions. Discover the Pub/Sub model and how to build live-updating services.

Previously in this course, we covered handling mutation errors to ensure our data modifications are robust and predictable. Now, we shift from request-response cycles to streaming data.
In the standard GraphQL model, the client initiates every interaction: you ask for data (Query), or you change it (Mutation). But what if your application needs to show a notification the moment a new record is created, or display a live stock price? This is where Subscriptions come in.
Understanding the Pub/Sub Model
At its core, a subscription allows the server to push data to the client over a persistent connection. Unlike HTTP, which is stateless and closes after each request, subscriptions typically use WebSockets to keep a long-lived channel open between the client and the server.
To manage this, we use the Publish/Subscribe (Pub/Sub) pattern:
- Publishers: Components (like a mutation resolver) that send an event when data changes.
- Subscribers: Clients that "listen" for specific events.
- Broker: A middleman (the PubSub engine) that routes messages from the publisher to all relevant subscribers.
Think of it like a newsletter: you (the subscriber) sign up to receive updates about a specific topic. When the author (the publisher) writes a new post, the distribution service (the broker) pushes that post to your inbox automatically.
Defining a Subscription Type
In GraphQL, you define a Subscription type in your schema just like you do for Query and Mutation. However, instead of returning a final value, a subscription field defines an AsyncIterator that yields data over time.
Here is a basic schema definition for a real-time message feed:
GraphQLtype Message { id: ID! content: String! } type Subscription { # The field name reflects the event the client is listening for messageAdded: Message! }
When a client executes this subscription, they receive a stream of Message objects whenever a new one is added to the system.
Worked Example: Implementing a Subscription
To implement this, you need a PubSub engine. For simple local setups, we often use PubSub from the graphql-subscriptions package.
First, initialize your PubSub instance:
JAVASCRIPTconst { PubSub } = require(CE9178">'graphql-subscriptions'); const pubsub = new PubSub(); // Constants for event names const MESSAGE_ADDED = CE9178">'MESSAGE_ADDED';
Next, update your mutation to publish an event whenever a new message is saved:
JAVASCRIPTconst resolvers = { Mutation: { addMessage: (_, { content }) => { const newMessage = { id: CE9178">'1', content }; // Publish the event to the broker pubsub.publish(MESSAGE_ADDED, { messageAdded: newMessage }); return newMessage; }, }, Subscription: { messageAdded: { // The subscribe method returns an AsyncIterator subscribe: () => pubsub.asyncIterator([MESSAGE_ADDED]), }, }, };
When addMessage is called, the pubsub.publish call triggers the messageAdded subscription for any connected clients currently listening.
Hands-on Exercise
- Install the necessary package in your project:
npm install graphql-subscriptions. - Add a
Subscriptiontype to yourtypeDefs. - Implement a
postCreatedsubscription in your current project. - Modify your existing
createPostmutation to triggerpubsub.publishwhenever a post is created. - Test the subscription using the Apollo Sandbox (or your preferred GraphQL client that supports WebSocket protocols).
Common Pitfalls
- Connection Overhead: Because WebSockets are stateful, you must manage connections carefully. If you have thousands of clients, you cannot simply keep them all connected to a single server instance. You'll eventually need a distributed broker like Redis, which we explore in Integrating Redis with WebSockets for Real-Time Apps.
- Missing Subscriptions in Schema: Beginners often forget that
Subscriptionis a root type. If you don't explicitly define it in your SDL, the server will not register it. - Payload Mismatch: Ensure the object you pass to
pubsub.publishmatches the structure expected by theSubscriptionresolver. If your subscription field ismessageAdded, the published object must have a key namedmessageAdded.
FAQ
Does every GraphQL server support Subscriptions? Not out of the box. While the GraphQL specification supports them, you need a transport layer (like WebSockets) configured in your server, which Apollo Server handles automatically if set up correctly.
Can I use HTTP for subscriptions? Standard HTTP is request-response based. While you can use techniques like Long Polling or Server-Sent Events (SSE), WebSockets are the industry standard for full-duplex, real-time GraphQL communication.
Are subscriptions better than polling? Yes. Polling forces the client to constantly ask "Is there new data?" (wasting bandwidth). Subscriptions let the server tell the client "I have new data" only when an update actually occurs.
Recap
Subscriptions enable real-time features by moving away from the request-response cycle. By using the Pub/Sub model, we can decouple the event trigger (the mutation) from the event listener (the client), allowing for fluid, reactive interfaces.
Up next: We will discuss how to secure your schema by implementing field-level authorization to ensure sensitive data remains protected.
Work with me

React & Next.js Dashboard / Admin UI Development
A clean, data-rich dashboard UI in React or Next.js โ charts, tables, and real-time data that your users will actually enjoy using.

Laravel SaaS MVP & Multi-Tenant App Development
Launch your SaaS MVP on Laravel โ multi-tenant, subscription-ready, and built by the engineer behind a platform serving 10,000+ paying users.


