Odyssey

Federated subscriptions with TypeScript & Apollo Server

Course overview and setupFederated subscriptionsSetting up subscriptionsSubscriptions over HTTP callbacksPubSub and resolversThe Subscription resolverReturning subscription dataUsing withFilterSynchronizing graph-wide updates
4. Subscriptions over HTTP callbacks
5m

Overview

Before we can send subscription operations through our federated graph, we need to tell our locally-running router (part of the rover dev process) exactly how it should handle subscription events.

In this lesson, we will:

  • Learn about the HTTP callback event loop
  • Use the router-config.yaml file to configure the router for subscriptions over HTTP callback

Subscriptions and router-config.yaml

To enable subscriptions in our federated graph, we'll turn back to the router-config.yaml file. This is the configuration file where we can provide all kinds of details about how the router should run—including how it should handle subscription events, and which protocol to use for which subgraphs.

Let's open up router/router-config.yaml.

First, we'll add a top-level property called subscription. On the level below this (indented in), we'll define two extra properties: enabled, which we'll set to true, and mode.

router-config.yaml
# ...other router config properties
subscription:
enabled: true
mode: # TODO

Beneath mode, we'll specify some additional properties. This is where we can enable one of two subscription methods: WebSockets (denoted as passthrough) and HTTP callbacks (denoted as callback). We'll stick with callback for this course.

Note: To explore all possible configuration options in the router.yaml file, check out the official documentation.

router-config.yaml
subscription:
enabled: true
mode:
callback:

Next, we'll add the remaining properties that nest beneath the callback property, and then walk through them one-by-one.

router-config.yaml
subscription:
enabled: true
mode:
callback:
public_url: http://127.0.0.1:4000/callback
listen: 127.0.0.1:4000
path: /callback
heartbeat_interval: 15s
subgraphs:
- messages
# This file specifies the settings the router should use when running
supergraph:
listen: 127.0.0.1:4000
include_subgraph_errors:
all: true
telemetry:
instrumentation:
spans:
mode: spec_compliant
headers:
all:
request:
- propagate:
named: "Authorization"
subscription:
enabled: true
mode:
callback:
public_url: http://127.0.0.1:4000/callback
listen: 127.0.0.1:4000
path: /callback
heartbeat_interval: 5s
subgraphs:
- messages

Error: mapping values are not allowed in this context at line # column

You might see this error if the indentation of your router-config.yaml is incorrect.

How to fix it: Check out the complete code in the collapsible section just above this one. Make sure that all of your subscription properties are correctly aligned, and that child properties are nested beneath their parent at just one level of indentation.

Still having trouble? Visit the Odyssey forums to get help.

public_url

The public_url property represents the router's public URL that subgraphs must be able to send new subscription data to. This is the "callback URL" that the router sends to the subgraph. Our locally running router runs on http://127.0.0.1:4000, and we've appended /callback as the specific endpoint the subgraphs should use when "calling back" to the router (this is the default value the router will use unless we provide a different value).

listen

The listen property specifies the IP address and port the router will listen on for subscription callbacks. We haven't changed it from the default value here; but note that for security reasons, it's best to expose a separate port that's available only through your internal network.

path

The path property states the specific path of our router's callback endpoint. It should match the value appended to the public_url. If you don't specify a path here, it takes the value of /callback by default.

You've probably noticed that our three properties, public_url, listen, and path, have a lot in common. In fact, it seems like we're repeating ourselves a little bit here!

Both of the values we've given for listen and path have already been provided on the public_url. So why are we listing them out separately again?

Our setup for this course is straightforward, but depending on the enterprise environment we're working with, we might encounter a lot more hoops to jump through. With a more complicated setup, these three fields will most likely be different from each other. For instance, it's best practice to expose a separate port for the listen property, one that's accessible exclusively through internal networks.

heartbeat_interval

The hearbeat_interval property specifies an interval at which the subgraph should "check in" with the router. By default, the router asks the subgraph to send a "check" message every five seconds.

Note: The heartbeat_interval property is optional. You might not want your subgraph constantly checking in—particularly if your architecture follows a pay-by-function-call model! You can disable these check-ins by passing disabled in place of the number of seconds.

subgraphs

Lastly, under subgraphs, we specify the names of the subgraphs that use the HTTP callback protocol to provide subscription data. We have just one: messages.

The subscription initialization

Let's see what this new configuration means for our graph. We'll walk through the subscription setup process using an example operation from earlier.

subscription SubscribeToMessagesInConversation($messageInConversationId: ID!) {
messageInConversation(id: $messageInConversationId) {
text
sentTime
}
}

When the router receives this operation, it creates the query plan and determines that the entire operation is the responsibility of the messages subgraph. So, it sends it onward—including extra information about how to call back. Here's what this looks like.

{
"query": "subscription SubscribeToMessagesInConversation(){...}", // remainder of subscription operation
"extensions": {
"subscription": {
"callbackUrl": "http://127:0.0.1:4000/callback/randomly-assigned-subscription-hash",
"subscriptionId": "randomly-assigned-subscription-hash",
"verifier": "XYZ", // a unique property
"heartbeatIntervalMs": 15000
}
}
}

That's a lot of helpful data! Let's take a closer look at what we're working with here.

In addition to the subscription operation itself, the object contains the callbackUrl and the heartbeatIntervalMs values that we provided in the router-config.yaml (with the exception of seconds being converted to milliseconds). Additionally, the router will assign a subscriptionId for the very specific operation it sends to the subgraph.

Finally, we have a property called verifier. The verifier is used to verify the subgraph's identity with the router every time it sends a new message—it's how the router knows who it's talking to and whether the source is legitimate.

A diagram of the router and subgraph, with the router providing the verifier that should be used in future communication

Upon receiving this big object from the router, the subgraph includes the verifier in its first response back to the router to make contact. The router responds with confirmation, and the subgraph initializes the subscription by sending back an empty GraphQL object. With that, setup is complete! And we're ready for updates.

The subscription loop

With our subscription setup complete, the loop begins. Here's what happens under the hood:

  1. Every five seconds, the subgraph takes on its emitter role and sends the router a "check" message. Kind of like saying "Are you still there?" every once in awhile—if the router responds, the loop continues.
  2. When the subgraph detects a subscription event (new data!) it sends the router a "next" message containing the data.
  3. If something goes wrong or the subscription should be terminated, the subgraph sends a "complete" message and the router ends the subscription.

You don't need to do anything special to handle these "check", "next" and "complete" messages. This is handled out-of-the-box by our Apollo Server implementations. These additional details can serve as a guide for anyone working on an implementation of the HTTP Callback Protocol.

If we do nothing else in our graph, the subgraph and router will continue checking in every five seconds. But as soon as we trigger some change to our pertinent data, the subgraph has something substantial to share. The router receives this new data, packages it up with anything else it needed to fetch across the graph, and returns it all to the client. And the loop goes on!

Re-running rover dev

We've provided a bunch of configuration for our locally-running router to use; now let's just restart the rover dev process and make sure that we're actually using it!

APOLLO_KEY="..." \
APOLLO_GRAPH_REF="..." \
rover dev \
--supergraph-config supergraph.yaml \
--router-config router-config.yaml

Run this command, passing in your own values for APOLLO_GRAPH_REF and APOLLO_KEY. And with that, we should have success!

==> your supergraph is running! head to http://localhost:4000 to query your supergraph

Error: Not connected to GraphOS. License violation.

You might see this error if your credentials are incorrect, or you've created your graph on a non-Enterprise organization.

How to fix it: Double-check that the graph you created in the first lesson of the course was added to an Enterprise organization. Then, rerun the rover dev command, first providing both values for APOLLO_KEY and APOLLO_GRAPH_REF.

APOLLO_GRAPH_REF="..." \
APOLLO_KEY="..." \
rover dev \
--supergraph-config supergraph.yaml \
--router-config router-config.yaml

If this still doesn't work, go back to your graph's settings. Under This Graph, locate the API Keys tab. Generate a new API key, and use this as the value for your APOLLO_KEY when you run the command.

Still having trouble? Visit the Odyssey forums to get help.

Practice

HTTP Callback Protocol
When implementing the HTTP Callback Protocol, the router and subgraph communicate over 
 
. The configuration property called 
 
 lets us set how frequently the subgraph should check in with the router. Including this property in the configuration file is 
 
. Whenever new data is available, the subgraph sends it to the router along with a special value called the 
 
, which confirms its identity with the router. This process can optionally include a separate component to manage the ongoing check-ins and data transmission called the 
 
.

Drag items from this box to the blanks above

  • heartbeat_interval

  • optional

  • communicator

  • checkin_interval

  • emitter

  • required

  • verifier

  • a callback URL

  • BFF

  • authorization

  • a long-lived, persistent connection

To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.
Code Challenge!

Complete the router configuration file below to enable subscriptions with HTTP callbacks. Set public_url to http://127.0.0.1:4000/proxy and heartbeat_interval to 10s. Enable subscriptions for the missions subgraph.

Key takeaways

  • The HTTP callback protocol allows the router and subgraph server to stay in contact, checking in periodically and sharing updates as they happen.
  • This protocol can optionally include a third mechanism, the emitter, which can take on the responsibility of checking in with the router as well as conveying new data.
  • The router provides the subgraph server with a callback URL where the subgraph (or emitter) can send its messages when checking in and sharing updates.
  • The router also provides a verifier, a unique value that the subgraph should include with every communication to verify its identity.

Up next

Our router process is ready to handle our subscriptions—now let's finish up our logic and start sending messages!

Previous
Next

Share your questions and comments about this lesson

Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              operations

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subscriptions

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              subscriptions

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              subgraphs

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraphs

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              subgraphs

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              fields

              A unit of data that belongs to a type in a schema. Every GraphQL query requests one or more fields.

              type Author {
              # id, firstName, and lastName are all fields of the Author type
              id: Int!
              firstName: String
              lastName: String
              }
              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subgraphs

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              query plan

              A strategy for executing an incoming operation efficiently. A query plan divides a single incoming operation into one or more operations that are each resolvable by a single subgraph.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              operation

              A single query, mutation, or subscription that clients send to a GraphQL server to request or manipulate data.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              GraphQL

              An open-source query language and specification for APIs that enables clients to request specific data, promoting efficiency and flexibility in data retrieval.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subscription

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              Apollo Server

              An open-source library for server-side GraphQL operation handling. It can be used as a monolithic GraphQL server or a subgraph server within a supergraph.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              graph

              A schema-based data model representing how different data elements interconnect and can be accessed.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraph server

              A GraphQL server which acts as a module of a supergraph. Subgraph servers can be written in any federation-compatible language or library.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraph server

              A GraphQL server which acts as a module of a supergraph. Subgraph servers can be written in any federation-compatible language or library.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subgraph

              A service in a federated GraphQL architecture. Acts as a module for a supergraph. Includes both GraphQL services and REST services integrated via Apollo Connectors.

              router

              The single access point for a federated GraphQL architecture. It receives incoming operations and intelligently routes them across component services before returning a unified response.

              subscriptions

              A long-lived, real-time GraphQL operation that enables real-time communication by allowing clients to receive data updates from the server when specific events or changes occur.

              NEW COURSE ALERT

              Introducing Apollo Connectors

              Connectors are the new and easy way to get started with GraphQL, using existing REST APIs.

              Say goodbye to GraphQL servers and resolvers—now, everything happens in the schema!

              Take the course