GraphQL

Endpoints and query interface

The GraphQL endpoint is available on the same base path as our Cloud REST endpoints, but under path /graphql.

The URL to be used for GraphQL queries will look similar to https://xxxxxxx.execute-api.eu-west-1.amazonaws.com/prod/graphql.

AppBoard also provides a graphical query interface called GraphiQL. It can be found at https://your-appboard-url.com/graphiql, and is protected by the regular appboard login.

Connecting types

The graphql schema is just an aggregator over the existing API. This means that a single graphql query will result in 1, or more requests, to the API.

query {
  thing(thingName: "00000040") {
    thingName
    domain
    domainConnection {
      id
      description
    }
  }
}

The query above will result in 2 requests in total. First, one single request to the Thing Management API, to get the thingName and domain fields. Then, the domainConnection will result in an additional request to the Domain API. Our schema uses the convention of {type}Connection to signal that additional requests may happen to return the data for {type}.

This is important to keep in mind to understand the potential cost and latency of a query.

Batching

To reduce the number of additional requests for {type}Connection fields, our resolve functions will leverage batching whenever possible.

query {
  allThings(searchOptions: {filter: {domains: ["domainA", "domainB"]}}) {
    things {
      thingName
      domain
      domainConnection {
        id
        description
      }
    }
  }
}

The query above will result in 3 requests in total. Even though the response may contain hundreds of things, they will all have a domain value of “domainA” or “domainB”, and the resolver can batch this internally to just 2 additional request. In some cases, depending on {type}Connection, this may be reduced to just 1 single additional request (if the “lookup” API allows for batch requests).

Queries that cannot be batched

Pay extra attention to many-to-many relations, as it’s not possible to batch these.

query {
  allDomains {
    domains {
      thingsConnection {
        pageInfo {
          totalCount
        }
        things {
          thingName
        }
      }
    }
  }
}

The query above will result in 1+N requests. First, 1 single request to list all domains. Then, for each domain, 1 request to list things for that domain. The things requests cannot be batched together to a single request. This is because the list of things for a domain is of unknown size (and possibly very large), and is therefore paginated.

Depending on the size of the data sets, many-to-many may result in a large number of additional requests. If you use connections in many-to-many relations, it’s highly recommended to use paging to narrow the number of items, which will reduce the number of potential requests.