Launch GraphOS Studio

Multipart HTTP protocol for GraphQL subscriptions

For GraphQL clients communicating with the Apollo Router

To execute on the , client apps do not communicate over WebSocket. Instead, they use HTTP with multipart responses. This multipart protocol is built on the same Incremental Delivery over HTTP spec that the Apollo Router uses to support the @defer directive.

Use this reference if you're adding protocol support to a new library. Apollo Client, Apollo Kotlin, and Apollo iOS all support this protocol. also provides network adapters for the Relay and urql libraries.

Executing a subscription

To execute a subscription on the Apollo Router, a GraphQL client sends an HTTP request with almost the exact same format that it uses for and requests.

The only difference is that the request should include the following Accept header:

Example header
Accept: multipart/mixed;subscriptionSpec="1.0", application/json


The value for boundary should always be graphql, and the value for subscriptionSpec should always be 1.0.

As subscription events occur, the sends back HTTP response "parts" that conform to the definition of multipart content specified in RFC1341.

An example response might look like this:

Content-Type: application/json
Content-Type: application/json
{"payload": {"data": { "newPost": { "id": 123, "title": "Hello!"}}}}
  • If the request uses HTTP/1, the response includes the Transfer-Encoding: chunked header.
  • If the request uses HTTP/2 (which provides built-in support for data streaming), chunked encoding is not used (and is in fact disallowed).


While a client subscription remains active, the Apollo Router sends periodic "heartbeat" response parts to prevent any intermediaries from closing the connection. The body of a heartbeat is an empty JSON object, which clients should ignore silently:

Heartbeat response part
Content-Type: application/json

Message and error format

This protocol differentiates between transport-level errors and GraphQL errors in response payloads themselves. This is because the GraphQL response format is defined in the GraphQL spec, and unexpected might be confusing or could even break client typing.

With the exception of heartbeats, every response part body includes a payload property, which contains standard GraphQL response properties. The payload property can be null if a transport-level error occurs.

If a GraphQL-level error occurs, the Apollo Router can sometimes still return partial data, and the subscription connection should remain open. These errors are provided within the payload property:

"payload": {
"errors": [...],
"data": {...},
"extensions": {...}

If a fatal transport-level error occurs, the router sends a message with a top-level errors and null payload field, then closes the connection:

"payload": null,
"errors": [...]

Both types of errors follow the GraphQL error format, but top-level errors never include locations or path.

Subgraph protocol: HTTP callback
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy