Search code examples
amazon-web-servicesgraphqlreverse-proxyapollo-federationgraphql-schema

Route GraphQL requests to APIs in different regions serving different content but using same schema


We deploy backend services with GraphQL API in multiple AWS regions. The GraphQL schema is the same for each region, but the services serve region specific data. Apollo federation does not seem to address this topic, because we do not want to merge different schema. Our problem is also not about choosing the closest region. Clients choose a specific region to access data served by that region.

With REST, a reverse proxy could forward a request to the target region based on path parameters. In GraphQL however, all requests are targeting the same endpoint.

What is a good practice to route GraphQL requests to different regions, which are using the same schema but serving different content?

EDIT: maybe it is also important to note that we are using GraphQL subscriptions as well. It would be nice avoiding connections to multiple endpoints in the client - if possible.


Solution

  • We went for Apollo Links. Each backend is deployed in a different region providing its own GraphQL API endpoint.

    The frontend keeps a list of all available region endpoints and sets up directional links. We can select the respective link by setting context variables.

    import { ApolloLink, HttpLink } from '@apollo/client';
    import { RetryLink } from '@apollo/client/link/retry';
    
    const directionalLink = new RetryLink().split(
      (operation) => operation.getContext().region === "us",
      new HttpLink({ uri: "http://us-endpoint/v1/graphql" }),
      new RetryLink().split(
        (operation) => operation.getContext().region === "eu",
        new HttpLink({ uri: "http://eu-endpoint/v1/graphql" }),
        new HttpLink({ uri: "http://au-endpoint/v2/graphql" })
      )
    );
    

    Pros

    • The approach scales with the number of regions, which are limited by earth - for now.
    • We can create and keep subscriptions to known endpoints without reverse proxy routing.
    • We can choose to iterate over all regions in the user access token...
    • ..., or we can choose to select a single region selected by the user.
    • The region endpoints are completely transparent to the UI once the links are set up.
    • As shown in the example, this even helps with differing version.

    Cons

    • Requests have to pass through quiet a chain of links. (Probably neglectable compared to network communication.)