I had written a post on doing a backend component in a multi platform project. While it works, there was some oversight on my part. Let's get into a bit of a deeper dive on GraphQL. Then explain how it plays out in the decision.

PreCursor

I have heard of GraphQL for several years. But had never taken the plunge into it. It seemed like a good idea, but I never saw a reason to leave REST. Then two things sort of clicked to me.

  • Is it best practice to do a select * from table?
  • I had been mulling over type providers from my F# days. An auto completed api endpoints sounds really nice.
  • Whitelisted queries, approving every query that can be run in production.

At work we have been switching to React and React Native. I've been looking over the best practices for React. The GraphQL binding, and loading only what you need, cached queries, whitelisted queries. All of those items seem like a big win.

GraphQL Specifications

Starting with the specification, which can be seen here. The specification is an open standard. Defining how GraphQL, handles responses, types, fragments, etc. It is the skeleton and core body of the backend. Any server to be GraphQL must be compliant with this specification.

Microservice or Not

Whether to use or not use graphql in a microservice approach. That is up to you, and outside of this discussion. In graphql parlance presenting one common gateway. Is referred to as API stitching.

This will take schemas from several different end points. Stitch them together into one cohesive whole. Then present it as one common schema.

graphql_gateway_overview

In the above the square is our stitched gateway. The two circles the various endpoints.

In the top example, we make a query like the following.

articles {
    id
    title
    description
}

This will hit the article service, and retrieve all articles. It does not hit the user service at all.

graphql_query_example

For the other service we can execute something like.

user {
    id
    name
}

It's the same at the prior example. We will only hit one service end point.

So you can either do one monolithic repository. Or multiple service end points.

Clients

A client is the way the data is gathered from the graphql server. It will provide benefits like caching, checking if the query matches the schema, data binding etc.

An example from react apollo

import gql from 'graphql-tag';
import { Query } from 'react-apollo';

const GET_DOGS = gql`
  {
    dogs {
      id
      breed
    }
  }
`;

const Dogs = ({ onDogSelected }) => (
  <Query query={GET_DOGS}>
    {({ loading, error, data }) => {
      if (loading) return 'Loading...';
      if (error) return `Error! ${error.message}`;

      return (
        <select name="dog" onChange={onDogSelected}>
          {data.dogs.map(dog => (
            <option key={dog.id} value={dog.breed}>
              {dog.breed}
            </option>
          ))}
        </select>
      );
    }}
  </Query>
);

We specify the query in the const of GET_DOGS. The <Query> tag is instaniated graphql client, that will connect to the target server.

This is just a brief over view of the idea of the client. But this should hopefully provide the bare essentials to understanding the client.

Framworks.

When we talk about frameworks, there are two portions. The backend, being a server or server tools. The client is connecting, and displaying the data. These are the ones I've found.

Disclosure I have focused in on Apollo.

Backend

  • API Gateway (graphql schema stitching.)
  • DataDog/PagerDuty integration
  • Tracing, performance graphs

Client

  • Local and remote data management (it can replace redux, mobx)
  • Data binding on components.
  • Caching, etc.

Caveats with Frameworks

Let's hone in on Apollo, for this example. There are two features I mentioned tracing and caching.

Tracing is done via the apollo tracing specification. The server must simply implement this specification. You can see that here.

Focus in on the supported servers. At this time Node.JS, Ruby, Scala, Java, and Elixir. So this is the first hitch I was mentioning. At work we were targeting python initially. But it's not supported by Apollo, at this time.

Next is caching, see here. The only supported server is Node.JS So even if we use Ruby, Scala, Java, etc. You still lose caching.

This is the biggest caveat with using GraphQL. Support for features is still best under the JavaScript ecosystem. Luckily alot of these also support either TypeScript or Flow. But if you have a large backend team in something outside of JavaScript. They will have to switch over to Javascript. Or backport features to their language of choice.

This is not a knock on GraphQL. It's a great technology, it's just young. As someone who likes enterprise language, and has been backporting features from javascript. The ecosystems just need time to work together.

Even Kotlin and GraphQL isn't overly nice. It's not bad, but it could be much nicer. The best helper library I've seen is graphql-spqr.. But note the issue about Kotlin support. You can't use data classes, due to an annotation bug. This seems like something ripe for the picking, to make easier.

In Closing

I will be providing an update to the graphql backend portion. Getting a running graphql backend. But sadly with the babel specific compilaton features for graphql. The react frontend I do will still be REST for the time being.