0
0
GraphqlHow-ToBeginner · 4 min read

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 withFilter or 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

ConceptDescriptionExample
Subscription FieldDefines event stream with optional filter argumentsmessageAdded(userId: ID): Message
Filter ArgumentsParameters to specify which events to receiveuserId: ID
Resolver FilteringLogic to send only matching eventswithFilter + asyncIterator + filter function
withFilterHelper to filter events before sendingwithFilter(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.