graphql-sse
Zero-dependency GraphQL subscriptions over Server-Sent Events for any HTTP/1 or HTTP/2 server.
Repository Health
Technical Analysis
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.
Used by 2 apps in this directory
GraphQL Hive
Developer Tools · Devops · Monitoring
Open-source GraphQL schema registry and observability platform with breaking change detection, federation support, and CI/CD integration for teams of any size.
twenty
CRM
The open-source CRM you build, ship, and version like the rest of your stack — with customizable objects, AI agents, and a TypeScript SDK.