# graphql-ws is coherent by design, which means you cannot mix it with subscriptions-transport-ws

> graphql-ws is a zero-dependency TypeScript implementation of the GraphQL over WebSocket Protocol, shipping server and client entry points plus adapters for ws, uWebSockets and Fastify. Its defining constraint is stated as a disclaimer: the library is not cross-compatible with the deprecated subscriptions-transport-ws, and both ends must implement the same protocol.

**enisdenjo/graphql-ws** — Coherent, zero-dependency, lazy, simple, GraphQL over WebSocket Protocol compliant server and client.

- Repository: https://github.com/enisdenjo/graphql-ws
- Website: https://the-guild.dev/graphql/ws
- Stars: 1,871 · Forks: 187
- Language: TypeScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/enisdenjo-graphql-ws

## The disclaimer is the product decision

Most libraries bury their transport assumptions. This one puts the incompatibility in the README under a heading, and states that graphql-ws and the GraphQL over WebSocket Protocol are not cross-compatible with the deprecated subscriptions-transport-ws and its accompanying protocol.

The instruction that follows is prescriptive: you must use graphql-ws coherently and implement the protocol on both sides, server and client. That rules out the most tempting migration path, where a new server is paired with an old client library to keep a deployment working for a week.

The protocol itself is a separate document in the repository, PROTOCOL.md, and the README points to it for the exact transport intricacies rather than summarising them here. That separation matters if you are implementing one side in another language, which the protocol document makes possible and the library framing invites.

The project also names its own alternative direction. For Server-Sent Events, the README directs you to a sibling project, graphql-sse, in the same author's repository. The choice between them is a transport decision made once and expensive to revisit.

## Zero dependencies is a stated goal, and the package shape proves it

The repository description calls the library coherent, zero-dependency, lazy and simple, and the zero part is checkable in the package metadata. Dependencies and devDependencies are both absent from the visible package.json content, so nothing from graphql-ws itself is forced onto your runtime.

What it does ship is a set of entry points, and the exports map is the clearest description of what it does. The root export resolves to the server implementation, with separate require and import conditions pointing at .cjs and .js builds and their matching declaration files. A ./client export exists for the browser side, and it is the entry point with a browser condition pointing at dist/client.js, which is how a bundler picks up the client build for a web target.

Then come the adapters, each with its own subpath: ./use/ws, ./use/uWebSockets and ./use/@fastify/websocket. Each subpath exists because WebSocket server libraries differ in how they hand you a socket. Rather than abstracting over all of them, the library exposes the hooks needed for each one and keeps them separate, which is what keeps the dependency count at zero while still supporting ws, uWebSockets and Fastify.

Engines require Node 20 or later, and the package declares type module while still shipping CommonJS builds through the require condition.

## A yarn 4 monorepo workflow with a patch file at the root

The build and development tooling is worth noting because it constrains what a contributor has installed. The package declares yarn 4.6.0 as its packageManager, and the repository carries a .yarn/ directory plus a .yarnrc.yml, which together mean Yarn Berry with its own checked-in state rather than a global Yarn 1.

A .node-version file pins the Node version used in development, matching the engines field.

PATCHES.md at the root is unusual for a library with no dependencies, and it points at a deliberate patch workflow rather than an accident. Such a file documents changes applied to the Yarn installation itself to make the toolchain behave on a given platform, which is the kind of detail that saves a new contributor an afternoon.

Releases go through changesets. The .changeset/ directory at the root, together with CHANGELOG.md, is the standard mechanism: a change is described in a changeset, and the version bump and changelog entry follow from merging it. The three most recent releases are v6.4.0 on 2026-10-13, v6.3.0 on 2026-09-24 and v6.2.2 on 2026-09-16, which is a cadence worth matching in your own dependencies if you want predictable upgrade windows.

## Docs, recipes and the protocol are three separate things

The README is short because the documentation lives on a website maintained by The Guild, which is also the project's home. There is a get started guide, a recipes section described as short and concise code snippets for common use cases, and a documentation section that is auto-generated by TypeDoc and then rendered on the site.

Auto-generated API reference is worth flagging for anyone assessing quality. It provides signatures and types generated from the source, which readers should still consult carefully. For a protocol library, the parts worth reading carefully are the type signatures rather than the descriptions.

The documentation split means a reader cannot work entirely from the repository. The README links out for getting started and for recipes, and links in for protocol details. If you are evaluating the library offline, PROTOCOL.md and the exports map are what you have to work with.

The website directory in the repository root is where that content lives, so the docs are versioned with the code even though they are read online.

## Where this sits against SSE and the older Apollo transport

Two comparisons are worth making explicitly, and the README supports both.

Against Server-Sent Events, graphql-sse is the sibling project by the same author, and the difference is one-way versus bidirectional. A SSE transport suits a client that receives pushes and sends occasional control, while a WebSocket transport carries operations in both directions over one connection. Choosing wrongly shows up as a connection held open per subscriber in a model that was not designed for it.

Against subscriptions-transport-ws, the difference is a protocol generation rather than a transport. The older library is deprecated, its protocol is different, and the README refuses compatibility rather than deprecating gracefully. That is a defensible position when the two protocols have enough in common that a silent mix-up would be worse than a hard error.

The practical upshot for an existing codebase is that a migration is not incremental on the transport layer. You can migrate the schema and the resolvers independently, but the client and the server socket handler have to change together.

## MIT terms, current maintenance, and what is not documented here

Licensing is MIT with the licence in LICENSE.md at the root, and CODE_OF_CONDUCT.md sits beside it. For a library that sits in the request path of a server, permissive terms remove one category of procurement friction.

Maintenance is current. The last push was on 2026-10-15, two days after v6.4.0, and the repository is not archived.

Two things a reader should know are simply not in the README. There is no statement about authentication or authorization, which for a WebSocket subscription server is the question most integrators arrive with, and there is no statement about connection limits or backpressure behaviour. The protocol document is the place to look for message level detail, and the recipes page is where a worked example for a specific server library would live.

There is also no performance claim anywhere in the README, which is the correct behaviour for a transport library and means you should benchmark it in your own stack rather than expect a published figure.

## Conclusion

graphql-ws is the right choice for a new WebSocket subscription stack where you control both ends and want no runtime dependencies, and it is the wrong choice for an existing Apollo setup still running subscriptions-transport-ws, because the README rules out cross compatibility rather than offering a bridge. Verify first that your server upgrade path exists on the other side of your client, since a GraphQL schema can be shared while a subscription transport cannot, and note that the package requires Node 20 or later.

## FAQ

### Is graphql-ws compatible with subscriptions-transport-ws?

No. The README states that graphql-ws and the GraphQL over WebSocket Protocol are not cross-compatible with the deprecated subscriptions-transport-ws and its protocol, and that you must implement the protocol on both server and client.

### Does graphql-ws have any runtime dependencies?

The package is described as zero-dependency and the package metadata declares no dependencies, with devDependencies absent as well. Adapters for ws, uWebSockets and Fastify are exposed as separate subpath exports.

### What Node version does graphql-ws require?

The engines field requires Node 20 or later, and the repository pins a development version in a .node-version file.

### Should I use graphql-ws or Server-Sent Events instead?

The README points to the sibling project graphql-sse by the same author if you want to use Server-Sent Events instead of a WebSocket transport.

### Where is the protocol graphql-ws implements documented?

In PROTOCOL.md at the repository root, which the README links as the place describing the exact transport intricacies used by the library.

## Sources

- [enisdenjo/graphql-ws on GitHub](https://github.com/enisdenjo/graphql-ws)
- [License: MIT](https://github.com/enisdenjo/graphql-ws/blob/master/LICENSE)
- [Project website](https://the-guild.dev/graphql/ws)
- [README](https://github.com/enisdenjo/graphql-ws/blob/master/README.md)
- [Releases](https://github.com/enisdenjo/graphql-ws/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/enisdenjo-graphql-ws
