DEV Community

Atlas Whoff
Atlas Whoff

Posted on

GraphQL Subscriptions: Real-Time Data With Apollo

GraphQL Subscriptions: Real-Time Data With Apollo

GraphQL queries and mutations are request-response. Subscriptions are persistent — the server pushes updates to connected clients.

When to Use Subscriptions

  • Live comments or reactions
  • Real-time dashboards
  • Collaborative editing notifications
  • Order status updates

For simple push (notifications, feeds), SSE is often simpler. Use subscriptions when clients also need to query the same GraphQL schema reactively.

Schema Definition

type Subscription {
  messageAdded(roomId: ID!): Message!
  orderStatusChanged(orderId: ID!): Order!
}

type Message {
  id: ID!
  content: String!
  author: User!
  createdAt: String!
}
Enter fullscreen mode Exit fullscreen mode

Server Implementation

import { PubSub } from 'graphql-subscriptions';

const pubsub = new PubSub();

const resolvers = {
  Mutation: {
    addMessage: async (_, { roomId, content }, { user }) => {
      const message = await db.messages.create({
        data: { roomId, content, authorId: user.id },
        include: { author: true },
      });

      // Publish to subscribers
      await pubsub.publish(`MESSAGE_ADDED:${roomId}`, { messageAdded: message });

      return message;
    },
  },

  Subscription: {
    messageAdded: {
      subscribe: (_, { roomId }, { user }) => {
        // Auth check before subscribing
        if (!user) throw new GraphQLError('Unauthorized');

        return pubsub.asyncIterableIterator(`MESSAGE_ADDED:${roomId}`);
      },
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

Client With Apollo

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

const MESSAGE_ADDED = gql`
  subscription MessageAdded($roomId: ID!) {
    messageAdded(roomId: $roomId) {
      id
      content
      author { name }
      createdAt
    }
  }
`;

function ChatRoom({ roomId }: { roomId: string }) {
  const { data } = useSubscription(MESSAGE_ADDED, {
    variables: { roomId },
  });

  // data.messageAdded arrives each time a new message is published
  return <MessageList newMessage={data?.messageAdded} />;
}
Enter fullscreen mode Exit fullscreen mode

WebSocket Transport

// Apollo Server with WebSocket support
import { createServer } from 'http';
import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';

const httpServer = createServer(app);
const wsServer = new WebSocketServer({ server: httpServer, path: '/graphql' });

useServer({ schema }, wsServer);

httpServer.listen(4000);
Enter fullscreen mode Exit fullscreen mode

Real-time features — subscriptions, SSE, WebSockets — plus the full GraphQL stack are part of the AI SaaS Starter Kit.

Top comments (0)