Working with Subscriptions

1. Defining Subscription Fields

RuleDetail
One root fieldOperation must select exactly one
Resolver returns AsyncIteratorYields events over time
NamingPast-tense or noun: messageAdded, orderUpdated

2. Setting Up Subscription Server

Example: graphql-ws + Apollo Server

import { useServer } from "graphql-ws/lib/use/ws";
import { WebSocketServer } from "ws";

const wsServer = new WebSocketServer({ server: httpServer, path: "/graphql" });
useServer({ schema, context: ctxFn }, wsServer);
TransportLibrary
graphql-wsModern, recommended
subscriptions-transport-wsDEPRECATED
SSEgraphql-sse

3. Subscribing to Events

Example: Resolver with PubSub

import { PubSub } from "graphql-subscriptions";
const pubsub = new PubSub();

const resolvers = {
  Subscription: {
    messageAdded: {
      subscribe: (_, { channelId }) => pubsub.asyncIterableIterator(["MESSAGE_ADDED:" + channelId])
    }
  }
};

4. Publishing Events

Example: Publish from mutation

Mutation: {
  postMessage: async (_, { channelId, body }, { db }) => {
    const message = await db.message.create({ data: { channelId, body } });
    pubsub.publish("MESSAGE_ADDED:" + channelId, { messageAdded: message });
    return message;
  }
}

5. Filtering Subscription Events

Example: withFilter

import { withFilter } from "graphql-subscriptions";

Subscription: {
  messageAdded: {
    subscribe: withFilter(
      () => pubsub.asyncIterableIterator(["MESSAGE_ADDED"]),
      (payload, vars, ctx) => payload.messageAdded.channelId === vars.channelId && ctx.user.canRead(payload)
    )
  }
}

6. Using Subscription Variables

PatternUse
Topic keySubscribe to specific room/channel
Filter argsServer-side filter via withFilter
Auth claimsFrom connection context

7. Handling Subscription Lifecycle

EventHandler
connectionInitAuth handshake, build context
subscribeValidate operation, return iterator
complete / disconnectCleanup resources, unsubscribe
ping/pongKeepalive for proxies

8. Implementing Real-time Updates

Use casePattern
ChatmessageAdded(channelId)
Live counterscountChanged(metricId)
NotificationsnotificationReceived(userId)
Live queriesMercurius live queries / Apollo client polling fallback

9. Using Subscription Resolvers

FieldPurpose
subscribeReturns AsyncIterator (required)
resolveOptional: transform payload before sending

10. Handling Subscription Errors

SourceStrategy
Auth failReject in connectionInit
Resolver throwSent as error message; subscription can continue
Connection dropClient should reconnect with backoff

11. Securing Subscriptions

LayerMechanism
connectionParamsSend JWT in init payload
Origin checkVerify Origin header
Per-event authRe-check in withFilter
Rate limitCap connections + events per user
TLSwss:// only in production