Federating subgraphs in Apollo

Create a supergraph using the Apollo object-based federation model.

With the Apollo federation model, the same object is constructed from two or more subgraphs. You can quickly enable subgraphs built (or proxied) in API Connect for GraphQL for Apollo federation.

Key Apollo federation constructs

Assume that there is a type Customer that gets its data the following two subgraphs:

  • customer subgraph:

    type Customer {
      id: ID!
      name: String
    }
  • order subgraph:

    type Customer {
      id: ID!
      orders: [Order]
    }
    type Order {
      customerId: ID!
      createdOn: Date!
      totalAmount: Float!
    }

Some part of Customer comes from the customer subgraph, and some from the order subgraph. To federate the two subgraphs in Apollo, each subgraph must identify how a specific Customer can be accessed, by providing two constructs:

  • Declare the unique key for Customer (for example, with @key (fields: "id"))
  • Provide the correct query for Apollo to execute when it has that key to get the appropriate part of the Customer object

Apollo federation also expects these aspects to be wrapped in new queries (called _service and _entities). API Connect for GraphQL generates the new queries for you.

Example: Federate API Connect for GraphQL customer and order subgraphs in Apollo

Let's see how this works with a real example in API Connect for GraphQL:

  • customer subgraph:
    type Customer {
      id: ID!
      name: String
    }
    type Query {
      customer (id: ID!): Customer
        @rest (...)
    }
    # Write the following new line in a separate file or same file
    # This tells Apollo that `id` is a key field for `Customer`
    
    extend type Customer @key(fields: "id")
  • order subgraph:
    type Customer {
      id: ID!
    }
    type Order {
      customerId: ID!
      createdOn: Date!
      totalAmount: Float!
    }
    type Query {
      orders (customerId: ID!): [Order]
        @dbquery (...)
    }
    # Write these four new lines in a separate file or same file
    # This tells Apollo that `id` is a key field for `Customer`
    # It tells StepZen that to generate `orders` for a `Customer`
    # it must query `orders` passing the right parameters
    
    extend type Customer @key(fields: "id") {
      orders: [Order]
        @materializer (query: "orders", arguments: {name: "customerId", field: "id"})
    }

These five lines (one in customer subgraph, and four in order subgraph) are all that is needed to prepare API Connect for GraphQL graphs for Apollo federation.

Additional Apollo federation directives

Apollo federation sometimes requires additional directives. API Connect for GraphQL supports these directives, but often, you do not need them:

  • @external, used to pass additional data to subgraphs outside the @key fields:
    type Query {
      ordersAfterDate (customerId: ID!, date: Date!); [Order]
        @dbquery (...)
    }
    extend type Customer @key(fields: "id") {
      orders (date: Date!): [Order] @external
        @materializer (query: "ordersAfterDate", arguments: {name: "customerId", field: "id"}, {name: "date", argument: "date"})
    }
  • @include and@link are not needed, StepZen automatically generates them.
  • @override: you can use this as the Apollo specifications define
  • @tag: you can use this as the Apollo specifications define
  • @inaccessible: you can use this as the Apollo specifications define

If the @rest and @dbquery in the preceding subgraphs were to be replaced by @graphql, what you do to prepare them for Apollo federation remains the same. You can proxy existing subgraphs (perhaps written in a way that they cannot be modified or made Apollo-federation-ready) and you can then make them ready in API Connect for GraphQL.

Resources