graphql-sse

Zero-dependency GraphQL subscriptions over Server-Sent Events for any HTTP/1 or HTTP/2 server.

Library
npm
v2.6.1
461stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
64/100Good
Development Activity56
Maintenance56
Community56
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
86/100Excellent
Architecture88
Code Quality90
Innovation85
Learning Curve82

graphql-sse is a zero-dependency implementation of the GraphQL over Server-Sent Events Protocol, giving GraphQL subscriptions, queries, and mutations a transport that works safely over plain HTTP/1 connections without requiring a WebSocket upgrade. It ships both a server-side handler and a browser/Node client, built directly against the graphql-js execution engine so any existing GraphQL schema can be exposed over SSE with a single createHandler() call.

On the server side, ready-made adapters wire the handler into Express, Fastify, Koa, raw Node http/http2, and the Fetch API, so it drops into serverless and edge runtimes as easily as a traditional Node server. The client supports two connection strategies — a distinct-connection mode that opens a new SSE stream per operation (ideal for HTTP/2) and a single-connection mode that multiplexes every subscription over one long-lived stream (built for HTTP/1 browsers) — complete with automatic reconnect and configurable retry/backoff.

What You Get

  • A protocol-compliant createHandler() that validates, executes, and subscribes GraphQL operations and streams results as SSE events
  • Framework-specific server adapters for Express, Fastify, Koa, Node http/http2, and the Fetch API
  • A createClient() for browsers and Node with distinct-connection and single-connection transport modes
  • Built-in reconnect logic with randomized exponential backoff and configurable retry attempts
  • Full TypeScript types generated for both server and client APIs, plus a published PROTOCOL.md specification

Common Use Cases

  • Adding GraphQL subscriptions to an app deployed behind a proxy or CDN that blocks WebSocket upgrades
  • Serving GraphQL subscriptions from serverless/edge functions where persistent WebSocket connections aren’t available
  • Replacing graphql-ws in HTTP/1-only environments while keeping the same graphql-js execution engine and schema
  • Streaming @defer/@stream incremental delivery results (ExecutionPatchResult) to clients over SSE
  • Building a browser client that reconnects automatically after network drops without custom retry code

Under The Hood

Architecture The package cleanly separates protocol logic from transport binding: src/common.ts defines the shared wire-format types and the print()/parseStreamData() helpers, src/parser.ts holds a hand-written chunked SSE parser, src/handler.ts implements the full server-side protocol state machine (stream registration, token-based single-connection mode, per-operation reservation via an ops map, and graceful completion/disposal), and src/client.ts implements the equivalent client-side connection and retry logic. Framework bindings live isolated under src/use/ (express.ts, fastify.ts, koa.ts, http.ts, http2.ts, fetch.ts), each translating a framework’s native request/response objects into the framework-agnostic Request/Response types the core handler expects — meaning the protocol implementation itself never changes across servers, only the thin adapter layer does. This design means adding support for a new server framework requires only a new adapter file, not changes to core logic.

Tech Stack Written entirely in TypeScript against the graphql-js execution engine (peer dependency graphql >=0.11 <=17), with zero runtime dependencies of its own. The build pipeline produces three output targets — ESM and CommonJS via tsc (tsconfig.esm.json / tsconfig.cjs.json) and a minified UMD bundle via Rollup with @rollup/plugin-typescript and @rollup/plugin-terser for direct browser script-tag use. The repo is a Yarn (v4, Berry) workspace pairing the library with a website package for its documentation site; API docs are auto-generated from TSDoc comments via TypeDoc. Releases are fully automated through semantic-release with conventional commits driving version bumps and changelog generation.

Code Quality The tests/ directory holds roughly 2,400 lines across four suites — parser.test.ts (wire-format edge cases), handler.test.ts (protocol behavior, including snapshot tests against snapshots/handler.test.ts.snap), client.test.ts (over 1,300 lines covering both connection modes, retry/backoff, and abort handling), and use.test.ts (framework adapter integration) — run with Vitest. CI (ci.yml) enforces check:format, check:lint, and check:type across the whole workspace on every push and PR, in addition to running the test suite, so formatting, linting, and type errors block merges rather than relying on local discipline. Error handling is explicit and typed (a dedicated NetworkError class distinguishes retryable network failures from fatal protocol errors), and the public API is fully typed with no use of any outside narrowly justified, commented exceptions.

What Makes It Unique Rather than relying on the browser’s native EventSource (which can’t set custom headers or send POST bodies), graphql-sse ships its own SSE chunk parser and connection layer, which is what lets it support the single-connection mode — multiplexing every subscription over one authenticated SSE stream via a token exchanged through a PUT request, distinct from the simpler distinct-connection mode that opens one stream per operation. This dual-mode design directly targets the HTTP/1 head-of-line-blocking problem that plain SSE has in browsers (a six-connection-per-origin limit), letting consumers pick the tradeoff that matches their server’s HTTP version rather than forcing one transport strategy on every deployment.

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