Skip to main content
GraphQL Fundamentals·Lesson 5 of 5

Subscriptions & Real-Time

GraphQL subscriptions push data to clients over a persistent WebSocket connection. When a mutation triggers an event, every subscribed client receives the update instantly.

Server Setup

Install the WebSocket transport:

npm install graphql-ws ws @graphql-tools/schema

Update your server to handle both HTTP and WebSocket connections:

Ctrl+Enter
HTML
CSS
JS
Preview

Client Subscription

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

const MESSAGE_SENT = gql`
  subscription OnMessageSent {
    messageSent {
      id text sender createdAt
    }
  }
`;

function ChatMessages() {
  const [messages, setMessages] = useState([]);

  useSubscription(MESSAGE_SENT, {
    onData: ({ data }) => {
      setMessages(prev => [...prev, data.data.messageSent]);
    },
  });

  return (
    <ul>
      {messages.map(msg => (
        <li key={msg.id}>
          <strong>{msg.sender}:</strong> {msg.text}
        </li>
      ))}
    </ul>
  );
}

Simulating Real-Time in the Browser

Ctrl+Enter
HTML
CSS
JS
Preview

PubSub in Production

The built-in PubSub from graphql-subscriptions is in-memory — it doesn't work across multiple server instances. For production, replace it with a Redis-backed PubSub:

npm install graphql-redis-subscriptions ioredis
import { RedisPubSub } from 'graphql-redis-subscriptions';
const pubsub = new RedisPubSub({
  connection: { host: 'localhost', port: 6379 }
});

Now publish and subscribe work across any number of server processes.

When to Use Subscriptions

Use caseRecommendation
Chat messagesSubscription ✓
Live notificationsSubscription ✓
Dashboard that refreshes every 30sPolling is simpler
Collaborative editingSubscription ✓
Long-running job statusSubscription or polling

Subscriptions add complexity (WebSocket infrastructure, connection management). Use them when truly real-time behaviour is required.