-
Notifications
You must be signed in to change notification settings - Fork 2k
docs: add guide on subscriptions #4406
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ overrides: | |
- xlink | ||
- composability | ||
- deduplication | ||
- NATS | ||
|
||
ignoreRegExpList: | ||
- u\{[0-9a-f]{1,8}\} | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
--- | ||
title: Subscriptions | ||
--- | ||
|
||
# Subscriptions | ||
|
||
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. | ||
|
||
This guide covers how to implement subscriptions in GraphQL.js, when to use them, and what to consider in production environments. | ||
|
||
## What is a subscription? | ||
|
||
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. | ||
|
||
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. | ||
|
||
## How execution works | ||
|
||
The core of subscription execution in GraphQL.js is the `subscribe` function. It works similarly to `graphql()`, but returns an `AsyncIterable` of execution results | ||
instead of a single response: | ||
|
||
```js | ||
import { subscribe, parse } from 'graphql'; | ||
import schema from './schema.js'; | ||
|
||
const document = parse(` | ||
subscription { | ||
messageSent | ||
} | ||
`); | ||
|
||
const iterator = await subscribe({ schema, document }); | ||
|
||
for await (const result of iterator) { | ||
console.log(result); | ||
} | ||
``` | ||
|
||
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. | ||
|
||
## When to use subscriptions | ||
|
||
Subscriptions are helpful when your application needs to respond to real-time events. For example: | ||
|
||
- Receiving new messages in a chat | ||
- Updating a live feed or activity stream | ||
- Displaying presence indicators (e.g., "user is online") | ||
- Reflecting real-time price changes | ||
|
||
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. | ||
|
||
## Implementing subscriptions in GraphQL.js | ||
|
||
GraphQL.js supports subscription execution, but you’re responsible for setting up the transport and event system. At a minimum, you’ll need: | ||
|
||
- A `Subscription` root type in your schema | ||
- A `subscribe` resolver that returns an `AsyncIterable` | ||
- An event-publishing mechanism | ||
- A transport layer to maintain the connection | ||
|
||
The following examples use the [`graphql-subscriptions`](https://github.com/apollographql/graphql-subscriptions) package to set up an in-memory event system. | ||
|
||
### Install dependencies | ||
|
||
Start by installing the necessary packages: | ||
|
||
```bash | ||
npm install graphql graphql-subscriptions | ||
``` | ||
|
||
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. | ||
|
||
### Set up a pub/sub instance | ||
|
||
Create a `PubSub` instance to manage your in-memory event system: | ||
|
||
```js | ||
import { PubSub } from 'graphql-subscriptions'; | ||
|
||
const pubsub = new PubSub(); | ||
``` | ||
|
||
This `pubsub` object provides `publish` and `asyncIterator` methods, allowing | ||
you to broadcast and listen for events. | ||
|
||
### Define a subscription type | ||
|
||
Next, define your `Subscription` root type. Each field on this type should return | ||
an `AsyncIterable`. Subscribe functions can also accept standard resolver arguments | ||
such as `args`, `context`, and `info`, depending on your use case: | ||
|
||
```js | ||
import { GraphQLObjectType, GraphQLSchema, GraphQLString } from 'graphql'; | ||
|
||
const SubscriptionType = new GraphQLObjectType({ | ||
name: 'Subscription', | ||
fields: { | ||
messageSent: { | ||
type: GraphQLString, | ||
subscribe: () => pubsub.asyncIterator(['MESSAGE_SENT']), | ||
}, | ||
}, | ||
}); | ||
``` | ||
|
||
This schema defines a `messageSent` field that listens for the `MESSAGE_SENT` event and returns a string. | ||
|
||
### Publish events | ||
|
||
You can trigger a subscription event from any part of your application using the | ||
`publish` method: | ||
|
||
```js | ||
pubsub.publish('MESSAGE_SENT', { messageSent: 'Hello world!' }); | ||
``` | ||
|
||
Clients subscribed to the `messageSent` field will receive this message. | ||
|
||
### Construct your schema | ||
|
||
Finally, build your schema and include the `Subscription` type: | ||
|
||
```js | ||
const schema = new GraphQLSchema({ | ||
subscription: SubscriptionType, | ||
}); | ||
``` | ||
|
||
A client can then initiate a subscription like this: | ||
|
||
```graphql | ||
subscription { | ||
messageSent | ||
} | ||
``` | ||
|
||
Whenever your server publishes a `MESSAGE_SENT` event, clients subscribed to | ||
`messageSent` will receive the updated value over their active connection. | ||
|
||
## Planning for production | ||
|
||
The in-memory `PubSub` used in this example is suitable for development only. | ||
It does not support multiple server instances or distributed environments. | ||
|
||
For production, consider using a more robust event system such as: | ||
|
||
- Redis Pub/Sub | ||
- Message brokers like Kafka or NATS | ||
- Custom implementations with persistent queues or durable event storage | ||
|
||
Subscriptions also require careful handling of connection limits, authentication, rate limiting, and network reliability. These responsibilities fall to your transport layer and infrastructure. |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Besides this unmaintained library, we have an alternative package
@graphql-yoga/subscriptions
that uses the standardEventTarget
, and it also allows you to use other event sources like Redis.And it is fully type safe compared to
graphql-subscriptions
;