GraphQL in a Micro Services Architecture

GraphQL stitching increases developer agility and productivity

Background

In a recent article Exploring Tokens with Stellar I mentioned in passing how the usage of GraphQL stitching in our approach to building out our solution. To understand how we addressed this in a simple and elegant manner, I will first share the overall topology of our solution.

Author note: As a result of strong interest on this topic, we have released the source code on GitHub on March 14, 2019 under the organization token-factory.

Growing pains with micro services in the context of GraphQL

As we built out the programming model using GraphQL, we found that the benefits of having discrete services for each of our capabilities allowed our teams to work quickly and iterate on the programming model while giving the typical benefits around micro services and 12 factor apps. On the other hand, separating out these services prevented the team from leveraging the full strength around more GraphQL advanced capabilities such as server-side batching and caching. At the same time, we were in parallel, trying to simplify the client side programming model and how Apollo initializes the client based upon a well defined endpoint was creating another set of pain points for the development team.

How GraphQL stitching solved our problem

To try to resolve our pain points, the team decided to see how others approached micro services architectures with GraphQL and quickly came across the idea of schema stitching. In our micro services architecture, each of our micro services had their own unique endpoint and routing rules configured for our Ingress Controller. This approach required the front end development team to define multiple Apollo clients to support the various endpoints or configure complex routing rules beyond the simple context path routing rules in the Ingress to support routing to various micro services endpoints. By enabling schema stitching, we were able to merge the schemas from the various micro services that represented the composite view of all of the backing GraphQL APIs and thus simplifying our client programming model. The result being a single GraphQL endpoint to program against. In addition, this allowed our client side programming model to really embrace GraphQL and batch queries that spanned multiple services which in the previous architecture was not possible.

Architecture of GraphQL stitching

GraphQL stitching is an additional runtime service that is deployed to an existing topology(see topology above). In our solution, we deployed a GraphQL Proxy that routed traffic between our Ingress Controller and the GraphQL endpoints. The core functionality is provided by a community Node.js module called graphql-tools with a set of well defined APIs that are required to be implemented. The role of the stitching is to import and merge the schemas from a defined set of GraphQL endpoints. This runtime service is responsible for mapping the inbound request payload to the appropriate endpoint as well as error handling and security.

Our approach to GraphQL stitching for our services

In the example below, I included the entire resource that is responsible for merging the schemas and initializing the the Apollo server with the various GraphQL mutations and queries. Please note that the stitching acts as a proxy to the actual services and is static once the schemas have been merged. So if you the stitched GraphQL schemas you are managing are volatile, you will want to have periodically monitor these endpoints for changes. In our example, we leverage Kubernetes Readiness and Liveness probes to track changes and trigger reloads of the service in the case of changes.

Introducing remote 3rd party schemas

One of the subtle items in this script can be seen on line 22

const STELLAR_NODE_URI = ‘https://core-test.gly.sh/graphql’

One of the most powerful things about moving to GraphQL stitching was the ability to consume 3rd party APIs and have them merged with your existing GraphQL APIs. The Stellar developer community is quite active and provides many useful assets for developers. The one that we rely upon heavily is a GraphQL enabled API tier that sits on top of a Stellar testnet’s Postgres database. This and other awesome examples of the power of the developer ecosystem can be found in the article Building Stellar Apps. This endpoint augmented our APIs to expose a set of rich GraphQL queries for each of the stellar core databases. Awesome stuff!

Conclusion

Having come from a REST API centric view of the world, GraphQL is truly a game changer with the ability to perform fine grained queries that are well suited for multiple front end applications. By leveraging GraphQL stitching, we have built out a robust API strategy that is both consumable and scalable with the ability to add additional micro services in the future.

Credits

I would also like to thank Luo Chongxin for driving the initial investigation and implementation of this work.