Skip to content

Commit 4e9df42

Browse files
docs: add guide on subscriptions (#4406)
Guide for subscriptions
1 parent e24e6a9 commit 4e9df42

File tree

3 files changed

+153
-0
lines changed

3 files changed

+153
-0
lines changed

cspell.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ overrides:
2727
- xlink
2828
- composability
2929
- deduplication
30+
- NATS
3031

3132
ignoreRegExpList:
3233
- u\{[0-9a-f]{1,8}\}

website/pages/docs/_meta.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const meta = {
2121
'abstract-types': '',
2222
'oneof-input-objects': '',
2323
'defer-stream': '',
24+
subscriptions: '',
2425
'cursor-based-pagination': '',
2526
'custom-scalars': '',
2627
'advanced-custom-scalars': '',

website/pages/docs/subscriptions.mdx

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
---
2+
title: Subscriptions
3+
---
4+
5+
# Subscriptions
6+
7+
Subscriptions allow a GraphQL server to push updates to clients in real time. Unlike queries and mutations, which use a request/response model, subscriptions maintain a long-lived connection between the client and server to stream data as events occur. This is useful for building features like chat apps, live dashboards, or collaborative tools that require real-time updates.
8+
9+
This guide covers how to implement subscriptions in GraphQL.js, when to use them, and what to consider in production environments.
10+
11+
## What is a subscription?
12+
13+
A subscription is a GraphQL operation that delivers ongoing results to the client when a specific event happens. Unlike queries or mutations, which return a single response, a subscription delivers data over time through a persistent connection.
14+
15+
GraphQL.js implements the subscription execution algorithm, but it's up to you to connect it to your event system and transport layer. Most implementations use WebSockets for transport, though any full-duplex protocol can work.
16+
17+
## How execution works
18+
19+
The core of subscription execution in GraphQL.js is the `subscribe` function. It works similarly to `graphql()`, but returns an `AsyncIterable` of execution results
20+
instead of a single response:
21+
22+
```js
23+
import { subscribe, parse } from 'graphql';
24+
import schema from './schema.js';
25+
26+
const document = parse(`
27+
subscription {
28+
messageSent
29+
}
30+
`);
31+
32+
const iterator = await subscribe({ schema, document });
33+
34+
for await (const result of iterator) {
35+
console.log(result);
36+
}
37+
```
38+
39+
Each time your application publishes a new `messageSent` event, the iterator emits a new result. It's up to your transport layer to manage the connection and forward these updates to the client.
40+
41+
## When to use subscriptions
42+
43+
Subscriptions are helpful when your application needs to respond to real-time events. For example:
44+
45+
- Receiving new messages in a chat
46+
- Updating a live feed or activity stream
47+
- Displaying presence indicators (e.g., "user is online")
48+
- Reflecting real-time price changes
49+
50+
If real-time delivery isn’t essential, consider using polling with queries instead. Subscriptions require more infrastructure and introduce additional complexity, especially around scaling and connection management.
51+
52+
## Implementing subscriptions in GraphQL.js
53+
54+
GraphQL.js supports subscription execution, but you’re responsible for setting up the transport and event system. At a minimum, you’ll need:
55+
56+
- A `Subscription` root type in your schema
57+
- A `subscribe` resolver that returns an `AsyncIterable`
58+
- An event-publishing mechanism
59+
- A transport layer to maintain the connection
60+
61+
The following examples use the [`graphql-subscriptions`](https://github.com/apollographql/graphql-subscriptions) package to set up an in-memory event system.
62+
63+
### Install dependencies
64+
65+
Start by installing the necessary packages:
66+
67+
```bash
68+
npm install graphql graphql-subscriptions
69+
```
70+
71+
To serve subscriptions over a network, you’ll also need a transport implementation. One option is [`graphql-ws`](https://github.com/enisdenjo/graphql-ws), a community-maintained WebSocket library. This guide focuses on schema-level implementation.
72+
73+
### Set up a pub/sub instance
74+
75+
Create a `PubSub` instance to manage your in-memory event system:
76+
77+
```js
78+
import { PubSub } from 'graphql-subscriptions';
79+
80+
const pubsub = new PubSub();
81+
```
82+
83+
This `pubsub` object provides `publish` and `asyncIterator` methods, allowing
84+
you to broadcast and listen for events.
85+
86+
### Define a subscription type
87+
88+
Next, define your `Subscription` root type. Each field on this type should return
89+
an `AsyncIterable`. Subscribe functions can also accept standard resolver arguments
90+
such as `args`, `context`, and `info`, depending on your use case:
91+
92+
```js
93+
import { GraphQLObjectType, GraphQLSchema, GraphQLString } from 'graphql';
94+
95+
const SubscriptionType = new GraphQLObjectType({
96+
name: 'Subscription',
97+
fields: {
98+
messageSent: {
99+
type: GraphQLString,
100+
subscribe: () => pubsub.asyncIterator(['MESSAGE_SENT']),
101+
},
102+
},
103+
});
104+
```
105+
106+
This schema defines a `messageSent` field that listens for the `MESSAGE_SENT` event and returns a string.
107+
108+
### Publish events
109+
110+
You can trigger a subscription event from any part of your application using the
111+
`publish` method:
112+
113+
```js
114+
pubsub.publish('MESSAGE_SENT', { messageSent: 'Hello world!' });
115+
```
116+
117+
Clients subscribed to the `messageSent` field will receive this message.
118+
119+
### Construct your schema
120+
121+
Finally, build your schema and include the `Subscription` type:
122+
123+
```js
124+
const schema = new GraphQLSchema({
125+
subscription: SubscriptionType,
126+
});
127+
```
128+
129+
A client can then initiate a subscription like this:
130+
131+
```graphql
132+
subscription {
133+
messageSent
134+
}
135+
```
136+
137+
Whenever your server publishes a `MESSAGE_SENT` event, clients subscribed to
138+
`messageSent` will receive the updated value over their active connection.
139+
140+
## Planning for production
141+
142+
The in-memory `PubSub` used in this example is suitable for development only.
143+
It does not support multiple server instances or distributed environments.
144+
145+
For production, consider using a more robust event system such as:
146+
147+
- Redis Pub/Sub
148+
- Message brokers like Kafka or NATS
149+
- Custom implementations with persistent queues or durable event storage
150+
151+
Subscriptions also require careful handling of connection limits, authentication, rate limiting, and network reliability. These responsibilities fall to your transport layer and infrastructure.

0 commit comments

Comments
 (0)