Service-oriented GraphQL API

Rohit Ravikoti

Rohit Ravikoti

COO & Co-founder @ Novvum • 2 min read

Service-oriented GraphQL API

For our most recent client, we had quite the challenging task of migrating their legacy REST API and MySql database into a GraphQL API.

Our client was a startup which was growing rapidly and had evolved over the years, so the majority of their database schema and REST endpoints were obsolete.

Given the conditions, we needed to build their back-end from the ground up.

Initially, we thought of going the microservicesroute by splitting up their database and business logic into individually maintained services. However, after reading DHH's post about the majestic monolith, we decided to forego the microservices architecture.

There would be too many difficulties regarding how to handle network failure as well as CI/CD for each of those services.

What we liked most about the microservices architecture was its modularity and the opportunity to work with multiple databases. This meant that even though our codebase would be structured as a monolith, it wasn't tightly coupled.

Each service would function as its own GraphQL schema connected to its own database. These graphql schemas would be then stitched together using schema-stitching by an overarching graphql gateway layer (the server which exposes our api).

So, how exactly does the gateway communicate with each of these individual services if they are GraphQL schemas of their own? That's where GraphQL bindings come in. A binding essentially generates an SDK from a schema provided to it.

Given the following schema:

type Query {
  user(where: UserWhereUniqueInput!): User

We can query its binding like so:

context.users.query({ where: { id: userId } });

Most of the examples out in the wild for graphql bindings use remote schemas that require network calls.

In this case, we are using locally defined schemas.

I will make another post on how to accomplish this, but if you can't wait, you can take a look at the code here:gitlab:// novvum / open-source / graphql-services-monorepo-starter

As a bonus, used graphql-cli to automatically generate the bindings and typescript types from our schema definition.

For our databases, we used prisma as our primary access layer since it already came with bindings.

This architecture gave us some great flexibility when it came to integrating third party services and unifying our API.