Efficient GraphQL Resolvers for FaunaDB

Deprecated blog

FaunaDB now has native GraphQL!

FaunaDB now has native GraphQL, so this blog has been deprecated. We recommend following these tutorials instead:

  1. Getting started with GraphQL
  2. GraphQL Relations
  3. Unique Constraints in GraphQL
  4. GraphQL Pagination

You can also check out the GraphQL Reference section in our docs to learn more about:

GraphQL is an API specification that standardizes how clients request data from servers, It is rapidly becoming a popular way to specify the data that backend services should provide to front end clients. It is independent of any underlying data model, and is routinely used to query relational, document, and graph databases, as well as other backend microservices such as search and analytics. This article covers a GraphQL performance technique for FaunaDB, and the lessons might be useful no matter which database you use.

Front end developers can add features and optimize the data they request, without making cumbersome change requests of backend API developers.

A GraphQL-based system decouples backend data layout from client requirements. This allows clients to specify the shape of data they are looking for, simplifying the process of creating new features. Instead of requesting a backend API change each time the front-end requires a new piece of data, the front end engineers can simply add the new field to the GraphQL query specification. If that field is already supported by the GraphQL resolver, then no changes are needed on the backend. Front end developers can add features and optimize the data they request, without making cumbersome change requests of backend API developers.

One consequence of this architecture is that the backend server must resolve the GraphQL query, converting it to requests for backend microservices. For instance an app client might request a blog post, it’s comments, and it’s commenter’s avatars. If the posts, comments, and avatars are all in different systems, GraphQL will issue requests in parallel when possible, and stitch the results back together. This hides the complexity of microservices from API users.

FaunaDB’s query language makes it easy to combine complex query fragments before sending them to the database.

However, for applications which are querying data already stored in a single database, breaking the query apart with resolvers and issuing multiple queries can create unnecessary bottlenecks. Intelligent batching is the answer. FaunaDB’s query language makes it easy to combine complex query fragments before sending them to the database. This means your GraphQL resolvers can compose query fragments into the optimal FaunaDB query. This leads to improved performance for users, while freeing developers to iterate on GraphQL queries.

Identify and Improve Business Inefficiencies
ShiftX Screenshot

The early success ShiftX experienced with FaunaDB inspired them to build a deeper GraphQL integration, which they are in the process of extracting into an open source library. To give a preview of how this looks for them, here is an example GraphQL request to load a process graph, which is made of edges and different types of nodes, along with associated issues:    timestamp

      
   query ReadProcess($id: ProcessId! ) {
    readProcess(id: $id) {
      id
      name
      owner {
        id
        email
      }
      nodes {
        id
        type
        narrative
        issueCount
        ... on ActionNode {
          actor {
            actorId
          }
        }
        ... on TransactionNode {
          initiator {
            actorId
          }
          recipient {
            actorId
          }
          channel {
            channelId
          }
        }
        ... on InteractionNode {
          initiators {
            actorId
          }
          recipients {
            actorId
          }
          channel {
            channelId
          }
        }
      }
      edges {
        id
        originId
        targetId
      }
      issues {
        page {
          id
          title
          description
          severity
          status
          nodeId
          created {
            timestamp
          }
        }
      }
      updated {
        timestamp
      }
      created {
        timestamp
      }
    }
  }

After the resolvers have parsed and combined it, a single query is issued to FaunaDB. It’s a little long to show here, but logically it is doing things like paginating over indexes of nodes and edges, and selecting the fields needed by GraphQL.

FaunaDB’s query language makes combining fragments easy, so GraphQL resolvers can compose queries programmatically. It’s only once the query reaches the top of the GraphQL tree that it needs to be sent to the database for processing. One query round trip is faster and easier to deal with.

If you are interested in GraphQL and FaunaDB, you can start with this simple tutorial. Watch this space for more GraphQL content, and more details on how ShiftX is using FaunaDB.