graphql-subscriptions

A reference PubSub engine and async-iterator helpers for building GraphQL subscription resolvers in Node.js

Library
npm
v3.0.0
1,618stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
48/100Fair
Development Activity0
Maintenance20
Community72
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
72/100Good
Architecture72
Code Quality74
Innovation55
Learning Curve85

graphql-subscriptions provides the small set of primitives a GraphQL server needs to implement subscriptions: a PubSubEngine abstract class defining publish/subscribe/asyncIterator methods, a simple in-memory PubSub reference implementation for development, and a withFilter helper that lets a subscription resolver filter which published events actually reach which subscribed client.

It does not implement subscription transport (WebSockets, SSE) itself — that’s handled by graphql-ws or subscriptions-transport-ws sitting in front of a GraphQL execution engine like Apollo Server or graphql-yoga. Instead, graphql-subscriptions defines the publish/subscribe contract those layers call into, and its in-memory PubSub is commonly swapped for a Redis- or Kafka-backed PubSubEngine in production, multi-instance deployments.

What You Get

  • PubSubEngine abstract class defining the publish/subscribe/asyncIterableIterator contract for subscription resolvers
  • An in-memory PubSub reference implementation for local development and single-process servers
  • withFilter() helper for scoping which published events reach which subscribed client based on resolver arguments
  • AsyncIterableIterator utilities usable directly in GraphQL subscription resolver functions
  • A stable, minimal interface that third-party PubSubEngine implementations (Redis, Kafka, MQTT, Google PubSub) target for compatibility

Common Use Cases

  • Wiring a GraphQL subscription resolver’s asyncIterator to an in-memory PubSub during local development
  • Filtering broadcast events to only the subscribers whose query arguments match (e.g. a specific channel or record ID) via withFilter
  • Swapping the in-memory PubSub for a Redis- or Kafka-backed PubSubEngine to support subscriptions across multiple server instances
  • Implementing a custom PubSubEngine for a message broker not covered by existing community packages

Under The Hood

Architecture - The package is small and single-purpose: pubsub-engine.ts defines the abstract PubSubEngine class, pubsub.ts implements the default in-memory version using Node’s EventEmitter, pubsub-async-iterable-iterator.ts adapts emitter events into an AsyncIterableIterator consumable by GraphQL subscription resolvers, and with-filter.ts wraps an existing asyncIterator with a predicate function to selectively drop events per-subscriber.

Tech Stack - Written in TypeScript with zero runtime dependencies and only a peer dependency on graphql (v15 or v16), compiled to CommonJS via tsc. It deliberately avoids depending on any transport library (ws, graphql-ws) or specific GraphQL server implementation, keeping it usable across the whole Apollo/graphql-js ecosystem.

Code Quality - Test coverage lives in src/test and is run via Mocha with --expose-gc (to test for event-listener memory leaks specifically), plus chai/chai-as-promised/sinon for assertions and spies, and istanbul/remap-istanbul for coverage reporting; tslint enforces style. The codebase is small enough (~600 lines) that its scope is easy to audit end-to-end, though release cadence has slowed significantly since the 3.0.0 release.

API Design - The public surface is deliberately minimal: new PubSub(), pubsub.publish(trigger, payload), pubsub.asyncIterableIterator(triggers), and withFilter(asyncIteratorFn, filterFn). This tiny, stable contract is what lets dozens of third-party PubSubEngine backends interoperate with any GraphQL server that expects this interface, at the cost of the in-memory implementation itself not scaling past a single process.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search