This document specifies the protocol that any GraphQL server can implement to register its schema with Apollo Graph Manager.
A reference implementation of this protocol is included in Apollo Server.
The following diagram illustrates the communication sequence for a GraphQL server (hereafter referred to as the edge server) reporting its schema to Apollo Graph Manager (Apollo):
- The edge server calls
reportServerInfo
, providing anEdgeServerInfo
object with the server's details as input.- The edge server does not include an
executableSchema
string in this request. - The edge server does include an
executableSchemaId
in theEdgeServerInfo
input. This is the SHA-256 hash of the edge server's schema, represented as a hexadecimal string. - If this or any other
reportServerInfo
request fails with a non-2xx response from Apollo, the edge server should retry after 20 seconds.
- The edge server does not include an
- Apollo responds with a
ReportServerInfoResponse
. This response tells the edge server:- How many seconds to wait before sending the next
reportServerInfo
request - Whether the next
reportServerInfo
request should include theexecutableSchema
that corresponds to theexecutableSchemaId
provided in the previous request.
- How many seconds to wait before sending the next
- After waiting the specified number of seconds, the edge server calls
reportServerInfo
again. This request includes anexecutableSchema
string if and only ifwithExecutableSchema
wastrue
in Apollo's most recentReportServerInfoResponse
. - Go to step 2.
The schema reporting protocol uses the following GraphQL types, referred to in Protocol sequence above:
# This type's fields are documented below.
input EdgeServerInfo {
bootId: String!
executableSchemaId: String!
graphVariant: String! = "current"
libraryVersion: String
platform: String
runtimeVersion: String
serverId: String
userVersion: String
}
type ReportServerInfoResponse {
inSeconds: Int!
withExecutableSchema: Boolean!
}
type Mutation {
service(id: ID!): ServiceMutation!
}
type ServiceMutation {
reportServerInfo(
"Only sent if previously requested i.e. received ReportServerInfoResponse with withExecutableSchema = true"
executableSchema: String,
info: EdgeServerInfo!
): ReportServerInfoResponse
}
Name | Type | Description |
---|---|---|
bootId |
String! |
A randomly generated UUID that's unique for each instance of your edge server. Set this value on server startup (a given value should not persist across restarts). |
executableSchemaId |
String! |
A unique identifier for the edge server's schema. Should be the hex representation of the schema document's SHA-256 hash. |
Name | Type | Description |
---|---|---|
graphVariant |
String! |
The name of the graph variant to register the schema to. The default value is current . |
serverId |
String |
A randomly generated ID that's unique for each instance of your edge server. Unlike bootId , this value should persist across an instance's restarts. In a Kubernetes cluster, this might be the pod name, whereas the container can restart. |
userVersion |
String |
An arbitrary string you can set to distinguish data sent by different versions of your edge server. For example, this can be the SHA of the Git commit for your deployed server code. We plan to make this value visible in Graph Manager. |
By providing these values in your requests, you'll help Apollo improve its service. For example, they'll help us identify whether a certain environment, platform, or version is causing a particular issue.
Name | Type | Description |
---|---|---|
runtimeVersion |
String |
The runtime that your edge server is running, such as node 12.03 . |
libraryVersion |
String |
The name and version of the server and/or reporting agent your edge server is using, such as apollo-server-2.8 or graphql-java-3.1 . |
platform |
String |
The infrastructure environment that your edge server is running in (localhost , kubernetes/deployment , aws lambda , google cloud run , google cloud function , AWS ECS , etc.) |
Two semantically identical schemas can look different to Graph Manager, for example if you rearrange the order of an object type's fields. To avoid this, all edge servers should normalize their schema before sending it to Graph Manager.
To normalize your schema, do all of the following:
- Apply stable sorting (such as alphabetical) to the order of all type, field, and argument definitions.
- Remove all redundant whitespace.
- Remove all comments (but not docstrings).
Runtime dependencies on your schema document might result in poor user experience in tracking your schema changes, or even throttling of service availability.
val info = EdgeServerInfo(..)
val schema = normalize("type Query { .. }")
var withSchema = false
function sendReport() {
val executableSchema = if (withSchema) null else schema
val response = reportServerInfo(info, executableSchema)
if (response.withExecutableSchema) {
withSchema = true
}
setTimeout(sendReport, response.inSeconds)
}
sendReport()