GraphQL subscriptions are the piece of the GraphQL spec built for real-time data: instead of a client asking for data once and getting a response, it opens a persistent connection and receives updates whenever the underlying data changes on the server. Queries fetch, mutations change, subscriptions notify. All three coexist in the same schema, and most GraphQL APIs use all three for different parts of an application.
What changed in 2026
graphql-ws fully displaced the older subscriptions-transport-ws protocol across the ecosystem, after years of the older library being effectively unmaintained but still widely deployed.
- GraphQL over Server-Sent Events gained traction as a lighter-weight alternative to WebSockets for subscriptions that only need server-to-client push, without the overhead of a full-duplex connection.
- Federation-aware subscriptions matured, making it more practical to run subscriptions across a federated graph split between multiple services, which used to be a significant gap.
- Managed subscription infrastructure grew, with hosted pub/sub backends purpose-built for GraphQL reducing the amount of custom scaling work teams had to do themselves.
How a subscription works end to end
- The client sends a subscription operation, structurally similar to a query, over a WebSocket (or SSE) connection instead of a normal HTTP request.
- The server registers the client as a listener for the relevant event, typically keyed by some argument, like a specific chat room ID or record ID.
- When the underlying data changes, usually triggered by a mutation somewhere, the server publishes an event to a pub/sub system.
- The subscription resolver receives the event and pushes a formatted payload to every connected client currently subscribed to it.
- The connection stays open until the client unsubscribes or disconnects.
Subscriptions vs polling vs webhooks
| Approach |
Connection type |
Best for |
Downside |
| Polling (repeated queries) |
Stateless, repeated requests |
Infrequent updates, simple clients |
Wasted requests, update delay |
| GraphQL subscription |
Persistent (WebSocket/SSE) |
Live UI updates, chat, dashboards |
Requires stateful infra, pub/sub |
| Webhook |
Server-to-server push, not GraphQL |
Backend-to-backend event delivery |
Not consumed directly by frontend clients |
Why subscriptions need a pub/sub layer
A naive subscription implementation resolves events in-process: a mutation handler directly calls the subscription resolver's publish function. That works for a single server instance in local development, but breaks the moment you run more than one server process, because a client connected to server A never hears about a mutation handled by server B. Production subscription setups almost always sit on top of a pub/sub backend — Redis pub/sub, a managed message broker, or a purpose-built service — so that any server instance can publish an event that reaches clients connected to any other instance.
Common pitfalls
- Treating subscriptions as a query replacement. Subscriptions typically deliver incremental events, not full state. Clients often need an initial query to fetch current state, then a subscription to stay updated — the subscription alone rarely gives you a complete picture on first connect.
- Forgetting connection lifecycle management. Authentication, reconnection after a dropped connection, and cleanup of stale subscriptions all need explicit handling; they do not come free with the spec.
- Fan-out cost at scale. A popular subscription topic, like a live sports score watched by thousands of clients, can create serious fan-out load on the pub/sub layer if not designed with that scale in mind from the start.
- Overusing subscriptions for low-frequency data. If something updates once an hour, a subscription adds operational complexity for no real benefit over a periodic query or a client-side refresh.
FAQ
Do I need Apollo Server to use GraphQL subscriptions?
No. Subscriptions are part of the GraphQL spec, not tied to any one implementation. Apollo, GraphQL Yoga, and other servers all support them, generally using the graphql-ws protocol underneath.
Can subscriptions work with a REST backend?
Subscriptions live at the GraphQL layer, but the events they publish can originate from anywhere — a REST service, a database change stream, a message broker. The GraphQL server just needs something to trigger the publish step.
Are GraphQL subscriptions the same as WebSockets?
No. WebSockets are a transport mechanism subscriptions commonly run over, but subscriptions are a GraphQL operation type with their own schema definition and resolver pattern layered on top.
How do I authenticate a subscription connection?
Typically during the WebSocket connection handshake, using a token passed in the connection parameters, since subscriptions do not use standard HTTP headers the same way a query request does.
Where to go next