Docs
Launch GraphOS Studio

GraphQL subscriptions in cloud supergraphs

Real-time data delivery across your services


Cloud support for is currently in preview.

You can also use subscriptions with an Enterprise self-hosted supergraph. See the Apollo Router documentation.

Cloud provide preview support for GraphQL :

subscription OnStockPricesChanged {
stockPricesChanged {
symbol
price
}
}

With a cloud supergraph, you can add Subscription to the schema of any that supports the graphql-transport-ws WebSocket protocol:

stocks.graphql
type Subscription {
stockPricesChanged: [Stock!]!
}

Clients can then execute subscriptions on your , which executes them on your .

NOTE

To use subscriptions with your cloud supergraph, you must first complete certain prerequisites.

What are subscriptions for?

GraphQL subscriptions enable clients to receive continual, real-time updates whenever new data becomes available. Unlike queries and , subscriptions are long-lasting. That means a client can receive multiple updates from a single subscription:

GraphOS RouterGraphQL ClientGraphOS RouterGraphQL ClientNew data availableNew data availableInitiates subscriptionSends new dataSends new data

are best suited to apps that rely on frequently changing, time-sensitive data such as stock prices, IoT sensor readings, live chat, or sports scores.

How subscriptions work

Subscribes
over WebSocket
(or via callback)
Can query for
entity fields
as needed
Subscribes
over HTTP
Client
GraphOS
Router
Stocks
subgraph
Portfolios
subgraph

  1. A client executes a GraphQL subscription against your over HTTP:

    Example subscription
    subscription OnStockPricesChanged {
    stockPricesChanged {
    symbol
    price
    }
    }
    • The client doesn't use a WebSocket protocol. Instead, it receives updates via multipart HTTP responses.
    • By using HTTP for subscriptions, clients can execute all GraphQL operation types over HTTP instead of using two different protocols.
    • Apollo Client, Apollo Kotlin, and Apollo iOS all support GraphQL subscriptions over HTTP with minimal configuration. See each library's documentation for details. also provides network adapters for the Relay and urql libraries.
  2. When your router receives a subscription, it executes that same subscription against whichever subgraph defines the requested stockPricesChanged in the code snippet above.

    • This communication usually does use a WebSocket subprotocol, for compatibility with most subgraph libraries.
    • With a , you can also configure an HTTP-callback-based protocol.
  3. The subgraph periodically sends new data to your router. Whenever it does, the router returns that data to the client in an additional HTTP response part.

    • A subscription can include federated fields that are defined in other subgraphs. If it does, the router first fetches those fields by the corresponding subgraphs, such as the Portfolios subgraph in the diagram above. These queries use HTTP as usual.

Prerequisites

Before you add Subscription fields to your subgraphs, do all the following in the order shown to prevent errors:

  1. Make sure you've created a cloud supergraph and connected your GraphQL API to it!

  2. Update your supergraph's build pipeline to use 2.4 or later.

    • Previous versions of Apollo Federation don't support subscription operations.
  3. If your specify an Apollo Federation version, modify them to use Apollo Federation 2.4 or later:

    stocks.graphql
    extend schema
    @link(
    url: "https://specs.apollo.dev/federation/v2.4"
    import: ["@key", "@shareable"]
    )
    type Subscription {
    stockPricesChanged: [Stock!]!
    }
    • You can skip modifying subgraph schemas that don't define any Subscription fields.
  4. In each subgraph with subscriptions, make sure the subgraph uses the graphql-transport-ws WebSocket protocol for subscriptions.

  5. In each subgraph with subscriptions, make sure the subgraph hosts its subscriptions WebSocket endpoint at the path /ws.

    • If your WebSocket endpoint is currently hosted at a different path, you can add /ws as an additional path instead of removing the original path. This is helpful if legacy clients will continue executing subscriptions on your subgraph directly using the original path.
  6. Deploy your updated subgraphs.

After you complete these prerequisites, you begin executing subscriptions on your cloud router.

Default configuration

Subscriptions are enabled automatically for with the following default router configuration:

subscription:
enabled: true
mode:
passthrough:
all:
path: /ws

Example execution

Let's say our supergraph includes the following subgraphs and partial schemas:

Products subgraph
type Product @key(fields: "id") {
id: ID!
name: String!
price: Int!
}
type Subscription {
productPriceChanged: Product!
}
Reviews subgraph
type Product @key(fields: "id") {
id: ID!
reviews: [Review!]!
}
type Review {
score: Int!
}

A client can execute the following subscription against our router:

NOTE

Remember, clients execute subscriptions against your router over HTTP!

Apollo Client for Web, Kotlin, and iOS all support HTTP-based subscriptions.

subscription OnProductPriceChanged {
productPriceChanged {
# Defined in Products subgraph
name
price
reviews {
# Defined in Reviews subgraph!
score
}
}
}

When our router receives this operation, it executes a corresponding subscription operation against the Products subgraph (over a new WebSocket connection):

subscription {
productPriceChanged {
id # Added for entity fetching
name
price
# Reviews fields removed!
}
}

NOTE

  • This operation adds the Product.id field. The router needs @key fields of the Product entity to merge entity fields from across subgraphs.
  • This operation removes all fields defined in the Reviews subgraph, because the Products subgraph can't resolve them.

At any point after the subscription is initiated, the Products subgraph might send updated data to our router. Whenever this happens, the router does not immediately return this data to the client, because it's missing requested fields from the Reviews subgraph!

Instead, our router executes a standard GraphQL against the Reviews subgraph to fetch the missing entity fields:

query {
_entities(representations: [...]) {
... on Product {
reviews {
score
}
}
}
}

After receiving this query result from the Reviews subgraph, our router combines it with the data from Products and returns the combination to the subscribing client.

Trying subscriptions with curl

To quickly try out HTTP-based subscriptions without setting up an Apollo Client library, you can execute a curl command against your cloud router with the following format:

Example curl request
curl 'https://main--my-org-supergraph.apollographos.net/graphql' -v \
-H 'accept: multipart/mixed; boundary="graphql"; subscriptionSpec=1.0, application/json' \
-H 'content-type: application/json' \
--data-raw '{"query":"subscription OnProductPriceChanged { productPriceChanged { name price reviews { score } } }","operationName":"OnProductPriceChanged"}'

This command creates an HTTP multipart request and keeps an open connection that receives new subscription data in multiple response parts:

--graphql
content-type: application/json
{}
--graphql
content-type: application/json
{"payload":{"data":{"productPriceChanged":{"name":"Croissant","price":400,"reviews":[{"score":5}]}}}}
--graphql
content-type: application/json
{"payload":{"data":{"productPriceChanged":{"name":"Croissant","price":375,"reviews":[{"score":5}]}}}}
--graphql
content-type: application/json
{"payload":{"data":{"productPriceChanged":{"name":"Croissant","price":425,"reviews":[{"score":5}]}}}}
--graphql--

NOTE

This example subscription only emits three events and then directly closes the connection.

For more information on this multipart HTTP subscription protocol, see this article.

Previous
Using @defer
Next
Platform API
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy

Company