0
0
GraphqlHow-ToBeginner · 4 min read

How GraphQL Subscriptions Work: Real-Time Data Updates Explained

GraphQL subscriptions allow clients to receive real-time updates by opening a persistent connection to the server, usually via WebSocket. When data changes, the server pushes updates to subscribed clients automatically without the need for repeated queries.
📐

Syntax

A GraphQL subscription uses the subscription keyword similar to query or mutation. It defines the event or data changes the client wants to listen to.

  • subscription: Starts the subscription operation.
  • Event or field name: Specifies what data changes to listen for.
  • Selection set: Defines the data fields to receive when an event occurs.
graphql
subscription OnMessageAdded {
  messageAdded {
    id
    content
    author
  }
}
💻

Example

This example shows a simple subscription that listens for new messages added to a chat. When a new message is added, the server sends the id, content, and author fields to the client in real-time.

javascript
const { ApolloServer, gql, PubSub } = require('apollo-server');

const pubsub = new PubSub();
const MESSAGE_ADDED = 'MESSAGE_ADDED';

const typeDefs = gql`
  type Message {
    id: ID!
    content: String!
    author: String!
  }

  type Query {
    messages: [Message!]
  }

  type Subscription {
    messageAdded: Message
  }
`;

const messages = [];

const resolvers = {
  Query: {
    messages: () => messages,
  },
  Subscription: {
    messageAdded: {
      subscribe: () => pubsub.asyncIterator([MESSAGE_ADDED]),
    },
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}`);

  // Simulate new messages every 3 seconds
  let id = 1;
  setInterval(() => {
    const newMessage = { id: id++, content: 'Hello ' + id, author: 'User' + id };
    messages.push(newMessage);
    pubsub.publish(MESSAGE_ADDED, { messageAdded: newMessage });
  }, 3000);
});
Output
Server ready at http://localhost:4000/ // Every 3 seconds, a new message is published and pushed to subscribed clients.
⚠️

Common Pitfalls

Common mistakes when using GraphQL subscriptions include:

  • Not using a persistent connection like WebSocket, which is required for real-time updates.
  • Forgetting to implement the subscribe resolver that returns an async iterator.
  • Trying to use subscriptions like queries or mutations without handling the continuous data stream.
  • Not managing connection lifecycle events, leading to memory leaks or dropped subscriptions.
javascript
/* Wrong: Using a query resolver for subscription */
Subscription: {
  messageAdded: () => {
    // This returns a single value, not a stream
    return { id: 1, content: 'Hello', author: 'User1' };
  },
}

/* Right: Using asyncIterator for streaming data */
Subscription: {
  messageAdded: {
    subscribe: () => pubsub.asyncIterator(["MESSAGE_ADDED"]),
  },
}
📊

Quick Reference

ConceptDescription
subscriptionKeyword to define a subscription operation
subscribe resolverReturns an async iterator to push data streams
PubSubUtility to publish and subscribe to events
WebSocketCommon protocol to keep connection open for updates
Selection setFields requested in subscription response

Key Takeaways

GraphQL subscriptions use persistent connections to push real-time data updates to clients.
The subscription resolver must return an async iterator to stream events.
WebSocket is the common transport protocol for subscriptions.
Subscriptions differ from queries by continuously sending data instead of a single response.
Proper connection and resource management is essential to avoid leaks and dropped updates.