w3resource

Advanced topics for managed federation


The following sections describe advanced features of managed federation with Apollo Graph Manager.

Removing an implementing service

To "de-register" an implementing service with Graph Manager, call apollo service:delete:

This action cannot be reversed!

apollo service:delete --serviceName=products

The next time it polls, your gateway obtains an updated configuration that reflects the removed service.

Include the --tag option to remove an implementing service from a variant other than the default variant (current):

apollo service:delete --serviceName=products --tag=staging

Inspecting your graph

To view the implementing services that make up your graph, you can use both the Apollo CLI and the Graph Manager UI.

Run apollo service:list to see a snapshot of the services that make up your graph, including their endpoints and when they were last updated.

Pushing configuration updates safely

Whenever possible, you should update your service configuration in a way that is backward compatible to avoid downtime. The single best way to do this is to minimize the number of breaking changes you make to your schemas.

Additionally, call apollo service:push for an implementing service only after all replicas of that service are deployed. This ensures that resolvers are in place for all operations that are executable against your graph, and operations can't access fields that do not yet exist.

In the rare case where a configuration change is not backward compatible with your gateway's query planner, you should update your service registry before you deploy your implementing services. Additionally, you should perform configuration updates that affect query planning separately from (and prior to) other changes. This helps avoid a scenario where the query planner generates queries that fail validation in downstream services or violate your resolvers.

Examples of this include:

  • Modifying @key, @requires, or @provides directives
  • Removing a type implementation from an interface

In general, always exercise caution when pushing configuration changes that affect your gateway's query planner and consider how those changes will affect your other implementing services.

Example scenario

Let's say we define a Channel interface in one service, and we define types that implement Channel in two other services:

# Channel service
interface Channel @key(fields: "id") {
  id: ID!
}
# Web service
type WebChannel implements Channel @key(fields: "id") {
  id: ID!
  webHook: String!
}
# Email service
type EmailChannel implements Channel @key(fields: "id") {
  id: ID!
  emailAddress: String!
}

To safely remove the EmailChannel type from your schema:

  1. Perform a service:push of the email service that removes the EmailChannel type from its schema.
  2. Deploy a new version of the service that removes the EmailChannel type.

The first step causes the query planner to stop sending fragments ...on EmailChannel, which would fail validation if sent to a service that isn't aware of the type.

If you want to keep the EmailChannel type but remove its assocation with the Channel interface, follow the same steps, but only remove implements Channel from your EmailChannel definition in the first step.

If the goal is not to remove the type altogether, but to only remove it from the interface, you can follow a similar procedure, but instead of removing the EmailChannel type altogether, only removing the implements Channel addendum to the type definition. This is because the query planner expands queries to interfaces or unions into fragments on their implementing types. For example, a query such as

query FindChannel($id: ID!) {
  channel(id: $id) {
    id
  }
}

will generate two queries, one to each service, like so:

# To Email service
query {
  _entities(...) {
    ...on EmailChannel {
      id
    }
  }
}
# To Web Service
query {
  _entities(...) {
    ...on WebChannel {
      id
    }
  }
}

Currently, the Apollo gateway expands all interfaces into implementing types, though a follow-up to the query-planning logic may make this only occur for interfaces that serve as entities (i.e. have a @key).

Previous: Setting up managed federation
Next: Securing your graph