How to handle orchestration on a Federated schema?

If I was to use Apollo federation on my GraphQL gateway, what is Apollo’s recommendation for handling orchestration?

Say I have a simple setup such this:

Typically in a gateway layer, you would handle orchestration which takes care of calling the microservices in a particular sequence. In this example, my gateway fetches the product information and then calls the review service with some of that data. So it requires a layer of orchestration which calls one micro service and then another.

However, in a federated gateway, from my understand it just exposes all the subgraphs in one graph and doesn’t appear to afford the ability to add any sequence logic to how some services might get called. I guess this could be done from the client but this would mean each client would need to duplicate this logic. For example, a web app and mobile consuming the same federated schema would have to implement the orchestration by themselves.

The only options I can think of would be to either add a layer between the client and a federated gateway to handle the orchestration. Alternatively, add resolvers into the gateway layer which use some http fetch library to make the GraphQL calls.

With option one, this seems like it might be overkill and adds an additional service which then requires maintaining / hosting etc.

Wiith option two, it would appears to defeat the purpose of using a federated schema. Unless of course in my context of each resolver, I have access to the underlying subgraphs. Is this possible at all?

What is Apollo’s recommended way of handling orchestration between subgraphs?

Hello :wave:

Using Apollo Federation you could define your subgraph schemas (corresponding to your services in your diagram above) as

# products subgraph
type Product @key(fields: "id") {
  id: ID!
  # plus any additional product fields that are returned by products subgraph
}

type Query {
  product(id: ID): Product
}

and

# reviews subgraph
type Review {
  id: ID!
  text: String
  rating: Float!
}

extend type Product @key(fields: "id") {
  id: ID!
  reviews: [Review!]!
}

This would be composed by the gateway to a single schema that is queryable by the clients

type Review {
  id: ID!
  text: String
  rating: Float!
}

type Product {
  id: ID!
  reviews: [Review!]! # this is resolved from reviews subgraph

  # plus any additional product fields that are returned by products subgraph
}

type Query {
  product(id: ID): Product
}

Gateway would then handle all the orchestration logic when clients would make the call to get the product.reviews field (resolve product info first and use the product ID to query the reviews). See Introduction to Apollo Federation - Apollo GraphQL Docs for additional details.

Thanks,
Derek