graphql-ws

Zero-dependency server and client implementing the GraphQL over WebSocket Protocol

Library
npm
v6.4.1
1,871 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
80 /100 Excellent
Development Activity 76
Maintenance 84
Community 60
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
78 /100 Good
Architecture 85
Code Quality 82
Innovation 78
Learning Curve 68

graphql-ws is a coherent, zero-dependency implementation of the GraphQL over WebSocket Protocol, providing both a server and a client that speak the same well-specified subprotocol for running GraphQL subscriptions, queries, and mutations over a single WebSocket connection. It ships adapters for popular runtimes (ws, uWebSockets.js, Bun, Deno, crossws) and frameworks (Express, Fastify, Apollo, Relay), replacing the older, deprecated subscriptions-transport-ws with a lazy, lifecycle-aware, and fully protocol-compliant alternative.

Maintained by The Guild, it is widely adopted across the GraphQL ecosystem as the de facto standard for WebSocket-based subscriptions, with first-class TypeScript types and an auto-generated protocol document describing every message exchanged between client and server.

What You Get

  • A protocol-compliant WebSocket client (createClient) with lazy connection, retry/backoff, and both Promise and async-iterator subscription APIs
  • A transport-agnostic server (makeServer) that you plug into any WebSocket implementation via a thin adapter
  • Ready-made adapters for ws, uWebSockets.js, Bun, Deno, crossws, and @fastify/websocket
  • A fully specified, versioned GraphQL over WebSocket Protocol document (PROTOCOL.md) so client and server implementations stay interoperable
  • Zero runtime dependencies — graphql itself is the only peer dependency

Common Use Cases

  • Adding real-time GraphQL subscriptions to an existing Node.js or edge WebSocket server
  • Building a GraphQL client that needs queries, mutations, and subscriptions over one persistent connection
  • Migrating off the deprecated subscriptions-transport-ws protocol to a maintained, spec-compliant alternative
  • Powering GraphQL subscriptions in serverless/edge runtimes like Bun, Deno, or Cloudflare via crossws

Under The Hood

Architecture - The library splits cleanly into three modules: common.ts defines the wire protocol (message types, close codes, and the graphql-transport-ws subprotocol name), client.ts implements a lazy, retrying WebSocket client exposing both a Promise-based subscribe and an async-iterable interface built on top of a small internal observable implementation, and server.ts implements a transport-agnostic makeServer that accepts any object satisfying a minimal WebSocket-like interface and drives the connection lifecycle (connection_init, ack, subscribe, next, complete) per the protocol spec. Runtime-specific adapters under src/use/ (ws, uWebSockets.js, Bun, Deno, crossws, @fastify/websocket) are thin shims translating each runtime’s WebSocket API into the shape makeServer expects, which is what lets one core implementation run everywhere. Tech Stack - Written in TypeScript with zero runtime dependencies; graphql is the sole peer dependency, and runtime-specific packages (ws, crossws, @fastify/websocket, uWebSockets.js) are optional peers pulled in only for the adapters actually used. The build uses pkgroll/Rollup to emit dual ESM/CJS output with matching .d.ts/.d.cts type declarations, and the package is tested with Vitest. Code Quality - The tests/ directory has dedicated suites for common protocol logic, the client, the server, and each runtime adapter (common.test.ts, client.test.ts, server.test.ts, use.test.ts), exercising the full connection lifecycle including error and close-code paths. Source files use extensive TSDoc comments (@category annotations feed the auto-generated TypeDoc site) and strict TypeScript (@tsconfig/strictest), giving strong compile-time guarantees around the message protocol’s discriminated unions. API Design - The public surface is small and consistent: createClient/subscribe on the client side and makeServer plus a runtime adapter on the server side, mirroring the same message vocabulary on both ends. Documentation is auto-generated from source comments and published to a dedicated docs site, and the standalone PROTOCOL.md gives implementers of other languages/runtimes an exact reference, which keeps the getting-started surface small despite the protocol’s completeness.

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