How to Filter Subscription Events in GraphQL
To filter subscription events in GraphQL, add arguments to your
subscription field and use those arguments in the resolver to send only matching events. This way, clients receive real-time updates filtered by criteria like IDs or status.Syntax
A GraphQL subscription with filtering uses arguments to specify which events to receive. The subscription field defines the event type and accepts filter arguments. The resolver uses these arguments to decide which events to push to the client.
Key parts:
subscription: Defines the real-time event stream.- Arguments: Parameters to filter events (e.g.,
userId). - Resolver: Logic that filters events based on arguments.
graphql/javascript
type Subscription { messageAdded(userId: ID): Message } // Resolver example const resolvers = { Subscription: { messageAdded: { subscribe: withFilter( () => pubsub.asyncIterator('MESSAGE_ADDED'), (payload, variables) => { return !variables.userId || payload.messageAdded.userId === variables.userId; } ) } } };
Example
This example shows a subscription that filters messages by userId. Only messages for the specified user are sent to the client.
javascript
const { PubSub, withFilter } = require('graphql-subscriptions'); const pubsub = new PubSub(); const typeDefs = ` type Message { id: ID! content: String! userId: ID! } type Subscription { messageAdded(userId: ID): Message } `; const resolvers = { Subscription: { messageAdded: { subscribe: withFilter( () => pubsub.asyncIterator('MESSAGE_ADDED'), (payload, variables) => { return !variables.userId || payload.messageAdded.userId === variables.userId; } ) } } }; // Simulate publishing messages setTimeout(() => { pubsub.publish('MESSAGE_ADDED', { messageAdded: { id: '1', content: 'Hello User 1', userId: '1' } }); pubsub.publish('MESSAGE_ADDED', { messageAdded: { id: '2', content: 'Hello User 2', userId: '2' } }); }, 1000);
Output
Client subscribing with userId='1' receives:
{
"data": {
"messageAdded": {
"id": "1",
"content": "Hello User 1",
"userId": "1"
}
}
}
Client subscribing without userId receives both messages.
Common Pitfalls
Common mistakes when filtering subscription events include:
- Not using
withFilteror similar logic, causing all events to be sent to all clients. - Forgetting to check if filter arguments are provided, which can block all events.
- Not matching the filter logic in the resolver with the subscription arguments.
Always ensure your resolver uses the filter arguments correctly to avoid sending unwanted data.
javascript
/* Wrong: No filtering, all clients get all events */ Subscription: { messageAdded: { subscribe: () => pubsub.asyncIterator('MESSAGE_ADDED') } } /* Right: Use withFilter to filter by userId */ Subscription: { messageAdded: { subscribe: withFilter( () => pubsub.asyncIterator('MESSAGE_ADDED'), (payload, variables) => { return !variables.userId || payload.messageAdded.userId === variables.userId; } ) } }
Quick Reference
| Concept | Description | Example |
|---|---|---|
| Subscription Field | Defines event stream with optional filter arguments | messageAdded(userId: ID): Message |
| Filter Arguments | Parameters to specify which events to receive | userId: ID |
| Resolver Filtering | Logic to send only matching events | withFilter + asyncIterator + filter function |
| withFilter | Helper to filter events before sending | withFilter(pubsub.asyncIterator('EVENT'), (payload, vars) => ...) |
Key Takeaways
Add arguments to your subscription field to specify filters.
Use resolver logic with filtering helpers like withFilter to send only matching events.
Always check if filter arguments exist before filtering to avoid blocking events.
Without filtering, all clients receive all subscription events.
Test subscriptions with different filter values to ensure correct event delivery.