GraphQL Subscriptions and Real-Time Data Updates in Node.js

GraphQL Subscriptions allow clients to receive real-time updates from the server. Unlike typical queries and mutations, subscriptions maintain an open connection and push data to clients whenever there is a change. This is useful for applications that require real-time updates like messaging apps, live dashboards, or collaborative tools.This chapter will explore GraphQL subscriptions in Node.js, from basic concepts to advanced implementation, with deep dives into real-world examples.

What are GraphQL Subscriptions?

A GraphQL Subscription is a way for a server to send real-time updates to the client through an open WebSocket connection. The client subscribes to specific events or data changes, and the server pushes updates as they happen.

Key Characteristics:

  • Real-Time Communication: Pushes data instantly when an event occurs.
  • WebSocket-Based: Uses WebSockets instead of HTTP, allowing persistent communication.
  • Efficient: Unlike polling, subscriptions only send data when there’s a change.

Setting Up GraphQL Subscriptions in Node.js

To implement GraphQL Subscriptions in Node.js, we’ll use:

  • Express: For our main API server.
  • Apollo Server: A GraphQL server supporting subscriptions.
  • graphql-ws or subscriptions-transport-ws: Libraries to handle WebSocket connections for GraphQL.

Step 1: Install Necessary Dependencies

				
					npm install express apollo-server-express graphql graphql-ws

				
			

Step 2: Create a Basic GraphQL Subscription Server

We’ll create a simple chat application where users can subscribe to new messages in real-time.

  1. Define the schema: It will include Message type, a Query for fetching messages, a Mutation for sending new messages, and a Subscription for listening to new messages.

  2. Implement resolvers: These will handle the queries, mutations, and the subscription.

				
					const express = require('express');
const { ApolloServer, gql, PubSub } = require('apollo-server-express');
const { useServer } = require('graphql-ws/lib/use/ws');
const { WebSocketServer } = require('ws');

// Initialize PubSub for handling subscriptions
const pubsub = new PubSub();
const MESSAGE_ADDED = 'MESSAGE_ADDED';

// Sample data
let messages = [
  { id: '1', content: 'Hello World!', user: 'John' },
];

// Define the GraphQL schema
const typeDefs = gql`
  type Message {
    id: ID!
    content: String!
    user: String!
  }

  type Query {
    messages: [Message]
  }

  type Mutation {
    addMessage(content: String!, user: String!): Message
  }

  type Subscription {
    messageAdded: Message
  }
`;

// Define resolvers
const resolvers = {
  Query: {
    messages: () => messages,
  },
  Mutation: {
    addMessage: (parent, { content, user }) => {
      const newMessage = { id: String(messages.length + 1), content, user };
      messages.push(newMessage);
      // Publish the new message event
      pubsub.publish(MESSAGE_ADDED, { messageAdded: newMessage });
      return newMessage;
    },
  },
  Subscription: {
    messageAdded: {
      subscribe: () => pubsub.asyncIterator([MESSAGE_ADDED]),
    },
  },
};

// Create an Express app and WebSocket server
const app = express();
const server = new ApolloServer({ typeDefs, resolvers });
const wsServer = new WebSocketServer({ noServer: true });
const PORT = 4000;

// Apply WebSocket server middleware
const httpServer = app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

// Integrate WebSocket with GraphQL Subscriptions
useServer({ schema: server.schema }, wsServer);

// Handle WebSocket connections
httpServer.on('upgrade', (request, socket, head) => {
  wsServer.handleUpgrade(request, socket, head, (ws) => {
    wsServer.emit('connection', ws, request);
  });
});

server.start().then(() => {
  server.applyMiddleware({ app });
  console.log(`Subscriptions ready at ws://localhost:${PORT}/graphql`);
});

				
			

Understanding the Code

  • PubSub: This is an in-memory event system used to broadcast events like messageAdded in real-time.
  • Subscription: Subscriptions are defined in the schema. In this example, the messageAdded subscription allows clients to listen for new messages.
  • WebSocket Setup: graphql-ws library handles the WebSocket protocol, while the PubSub mechanism publishes the message events to all subscribed clients.

Querying and Subscribing in GraphQL

Once your server is running, clients can use queries and subscriptions.

Subscribing to New Messages

To subscribe to new messages, the client sends the following subscription query

				
					node -v
npm -v
subscription {
  messageAdded {
    id
    content
    user
  }
}

				
			

This keeps the connection open, and whenever a new message is added, the client will automatically receive the update.

Adding a New Message

To add a new message, the client uses a mutation:

				
					mutation {
  addMessage(content: "Hello!", user: "Alice") {
    id
    content
    user
  }
}

				
			

Whenever this mutation is called, the message is added to the chat, and all clients subscribed to the messageAdded event will be notified in real-time.

Advanced Topics in GraphQL

1. Subscription Filters

You may want to allow clients to subscribe to specific events or data changes based on certain conditions. This can be done by filtering subscriptions on the server.

Example: Filter Messages by User

				
					Subscription: {
  messageAdded: {
    subscribe: (parent, { user }) => {
      return pubsub.asyncIterator(MESSAGE_ADDED).filter(message => message.user === user);
    },
  },
}

				
			

In this case, clients would subscribe to new messages for a specific user.

				
					subscription {
  messageAdded(user: "John") {
    id
    content
    user
  }
}

				
			

2. Scaling Subscriptions

While PubSub works well for small applications, it’s not ideal for large-scale deployments because it only works in-memory. To scale, use systems like Redis, Kafka, or RabbitMQ to handle subscriptions across multiple instances of your app.

To use Redis for subscription events:

				
					npm install graphql-redis-subscriptions ioredis

				
			

Then replace the PubSub with Redis:

				
					const { RedisPubSub } = require('graphql-redis-subscriptions');
const Redis = require('ioredis');
const pubsub = new RedisPubSub({
  publisher: new Redis(),
  subscriber: new Redis(),
});

				
			

This setup allows your subscriptions to scale across multiple instances of your app.

3. Authentication in Subscriptions

You may need to authenticate users before allowing them to subscribe. This can be done by verifying tokens inside the WebSocket connection.

				
					const { useServer } = require('graphql-ws/lib/use/ws');

useServer({
  onConnect: (ctx) => {
    const token = ctx.connectionParams.authorization;
    const user = jwt.verify(token, 'secret-key');
    return { user };
  },
}, wsServer);

				
			

In this example, the client must pass an authorization token with the WebSocket connection, and the token is verified before the subscription is allowed.

Real-World Use Cases for Subscriptions

1. Real-Time Chat Applications

GraphQL Subscriptions can power live chat systems. As new messages are sent, all users receive updates instantly.

2. Live Dashboards

You can use subscriptions to build live dashboards that display real-time metrics, stock prices, or IoT sensor data.

3. Collaborative Editing

In applications like Google Docs, GraphQL subscriptions can be used to push changes to all users working on the same document in real time.

4. Notification Systems

Subscriptions are great for pushing real-time notifications, such as alerts for new messages, social media interactions, or important system events.

 

GraphQL Subscriptions bring real-time functionality to your API by maintaining an open WebSocket connection and allowing clients to receive updates as they happen. In this chapter, we've covered how to set up subscriptions in a Node.js environment, the role of PubSub, handling WebSockets, and some advanced topics like filters, scaling, and authentication.Subscriptions are perfect for applications that need to push real-time data to clients efficiently and are becoming increasingly popular for modern web and mobile apps. This chapter gives you a complete overview of building, scaling, and securing GraphQL Subscriptions, eliminating the need for any further resources on the subject. Happy coding !❤️

Table of Contents

Contact here

Copyright © 2025 Diginode

Made with ❤️ in India