GraphQL Subscriptions: Why we use SSE/Fetch over Websockets - WunderGraph

Jens Neuse
CEO & Co-Founder at WunderGraph
April 25, 2022·10min read
Last updated on September 9, 2025

Editor's Note: While this post provides great insights and mainly focuses on our product WunderGraph SDK, we’d like to introduce you to WunderGraph Cosmo.

As our main offering, Cosmo is designed to revolutionize API and GraphQL management. If you are exploring a GraphQL Federation solution, take a look at the key features of WunderGraph Cosmo to see how it can streamline and enhance your API workflows.

WunderGraph Cosmo is the complete solution for GraphQL Federation, providing a powerful and streamlined alternative to Apollo. Cosmo empowers teams to seamlessly compose, govern, and extend APIs across distributed microservices, enhancing performance, security, and scalability. By simplifying the complexities of managing federated architectures, Cosmo enables enterprises to focus on innovation and scaling with unmatched efficiency and ease.

State of GraphQL Federation 2026

How are teams governing schema changes, handling production traffic, and measuring Federation success? Share your experience and get early access to the full report. For every valid survey completed, we'll donate $30 to UNICEF.

Take the Survey

WunderGraph exposes GraphQL Subscriptions over SSE (Server-Sent Events) or Fetch (as a fallback). This post explains why we've decided to take this approach and think it's better than using WebSockets.

What is a GraphQL Subscription?

GraphQL Subscriptions allow a client to subscribe to changes. Instead of polling for changes, the client can receive updates in real-time.

Here's a simple example from our GraphQL Federation Demo:

  1. This is based on Apollo Federation. Once the "product" microservice has a price update, WunderGraph joins the data with the reviews from the "review" microservice, does an additional join with some user information from the "user" microservice, and sends the data back to the client.
  2. The client gets this as a stream of data. This way, the user interface can be updated in real-time.

Traditional ways of implementing GraphQL Subscriptions

The most widely adopted way of implementing GraphQL Subscriptions is to use WebSockets. The WebSocket API is an HTTP 1.1 standard that's usually supported by all modern browsers. (According to caniuse.com, 94.22% of all browsers support the WebSockets API)

First, the client sends an HTTP Upgrade request, asking the server to upgrade the connection to a WebSocket. Once the server upgrades the connection, both the client and the server can send and receive data by passing messages over the WebSocket.

Problems with WebSockets

The WebSocket API is an HTTP 1.1 standard

Most websites nowadays use HTTP/2 or even HTTP/3 to speed up the web. HTTP/2 allows for multiplexing multiple requests over a single TCP connection. This means that the client can send multiple requests at the same time. HTTP/3 improves this even further.

What's problematic is that if your website is mixing both HTTP/1.1 and HTTP/2, the client will have to open multiple TCP connections to the server.

Clients can easily multiplex up to 100 HTTP/2 requests over a single TCP connection, whereas with WebSockets, you're forced to open a new TCP connection for each WebSocket.

WebSockets are stateful

Another problem with WebSockets is that the client and the server have to keep track of the state of the connection. If we look at the principles of REST, one of them states that requests should be stateless.

Stateless in this context means that each request should contain all the required information to be able to process it.

Examples of using GraphQL Subscriptions with WebSockets

  1. Send an Authorization header with the Upgrade Request: Each WebSocket connection starts with an HTTP Upgrade request. However, this approach is not very practical as it relies on previously sent headers.
  2. Send an Auth Token with the "connection_init" WebSocket Message: While this can be practical, it also creates statefulness and could lead to security issues.
  3. Send an Auth Token with the "subscribe" WebSocket Message: This may seem practical, but it poses security risks and is inefficient.

WebSockets allow for bidirectional communication

This is not necessary for GraphQL Subscriptions and can lead to issues with server load.

WebSockets are not ideal for SSR

Server-Side Rendering with WebSockets poses challenges as connections have to be established before rendering can begin.

Summary of the Problems with GraphQL Subscriptions over WebSockets

Why we chose SSE (Server-Sent Events) / Fetch to implement GraphQL Subscriptions

SSE and Fetch are stateless APIs, straightforward to use, and can be secured easily. Both APIs can leverage HTTP/2, enhancing performance.

Advantages of SSE/Fetch

Conclusion

Implementing GraphQL Subscriptions with SSE/Fetch offers a modern and effective solution to overcome the limitations associated with WebSockets.