GraphQL is clearly the rage these days. Everyone out there seems to be talking about. But I must say, all the attention is very well deserved.
Since the very beginning of Space Cloud, we have given a lot of emphasis on the APIs we expose to our users. Initially, we settled in on HTTP and websockets since that was one thing supported by all browsers consistently.
As we started adopting other platforms and languages as well, HTTP and websockets became a big nuisance to manage. Each platform has its own specific form of consuming HTTP endpoints, and doing that amount of work for each language didn’t seem like a great way forward.
We needed a higher abstraction to work on.
Before we get to the reasons we choose gRPC and then why we moved to GraphQL, let’s talk about the specific use case we were dealing with.
The Use Case
To be a little more specific, we needed to design the APIs for the database module. The requirement was to support ad-hoc CRUD operations, including transactions via a unified API for each platform.
Things don’t really end there. Since we also support subscribing on result set changes, we needed a bi-directional transport layer to handle the realtime workloads.
After a few hours of brainstorming, we came to the following requirements:
- A request-response semantic for the CRUD operations.
- Bi-directional socket like connection for pushing realtime updates.
- A transport layer to handle network failures and reconnections automatically.
- A protocol which can be supported on all platforms (browsers, mobile, Game engines).
At first, websockets do seem to be a great fit.
They work on almost every platform, are completely bi-directional and are extremely lightweight. In fact, Space Cloud supports its HTTP/Websocket till date since it was such a great experience to work with.
We went ahead with this strategy and made our JS client using it. We made our own transport layer to deal with reconnections, queueing of messages and everything.
Just as we were about to declare ourselves the kings of the Backend as a Service world, we realised there were at least 4 more programming languages we had to support. Doing the same for each one of them was close to impossible.
Client drivers are important, but we are a backend team. We did not have the resources to handle that.
gRPC to the rescue!
Just around this time, we came across gRPC.
Just to be clear, gRPC is an open-source RPC framework. gRPC is schema driven. It generates client and server stubs based on the schema we provide. All communications between the client and server are taken care off. Using gRPC is as simple as calling a function on the client stub, which invokes a function on the backend. The rest is magic!
The best part about gRPC is that it supports bi-directional streaming out of the box. This means it can provide us with a neat websocket like API for our realtime workloads.
If I haven’t mentioned this already, gRPC provides client stubs in more than 7 languages! Each client handles network failures and the other cool things automatically.
This fact alone was enough for us to join the gRPC bandwagon and become the kings of the Backend as a Service world. It helped us release a golang and python client in no time.
Unfortunately, the awesomeness ends there.
The bad parts
Being schema driven meant that we needed to provide it the model of our data for it to work. This was a bit of a problem since we would never know upfront, what data our users are going to work with.
We settled with a JSON over gRPC kind of setup. This was less than ideal since one major selling points of gRPC is protobuf which is a binary based protocol. In essence, the high-performance gRPC framework worked slowly for us since we had two layers of parsing to be done.
Things don’t end there. Since we had this ugly JSON over protobuf strategy, our client wrappers had to do a little more work to provide an easier API to consume.
Also, handling streaming responses in some environments wasn’t very intuitive at first.
Soon, we realised that we would not be able to cover all the popular languages with this approach. Most of the code we write is in go and js, so supporting client drivers in other languages wouldn’t be practical.
After a lot of work, we decided to let go of the custom API which we had built. Custom APIs are great to get things started off really quick, but you’ll have to do a lot of work to get the ecosystem in place.
After days of going through Google and Medium, we realised that GraphQL tends to solve this ecosystem aspect beautifully.
GraphQL is an API query language. In other words, it’s the equivalent of SQL for your web servers.
You describe what you want to do in your query, similar to SQL. The server parses the request and gives you the answer in a format to match your query.
Due to its graph-like query structure, it helped us achieve way more than what we could dream of. Here are some of the things which are now possible in Space Cloud because of GraphQL:
- Select only those fields which you are interested in. (Helps save a lot of bandwidth)
- Cross-database joins. (Yes we can now do that!!)
- Joining data from databases and remote services
- No need to worry about client drivers ever again. (Special thanks to Apollo for being so awesome)
Apart from that, there is a huge wave of GraphQL, which seems to be expanding by the day. This makes it that much easier for our users to learn Space Cloud using the ecosystem they are already a part of.
Want to take things for a spin? Try our quick start guide and experience the power of GraphQL first hand.
Choosing GraphQL over gRPC was a big decision for us. Having to let go of our custom APIs in favour of an emerging standard is difficult.
The future, however, seems to be amazing. With the ability to do cross-database joins and joining results of microservices, we now stand the chance of truly becoming the kings of the Backend as a Service world.
We will soon be porting all our functionalities to GraphQL to try and make everything accessible via the same API. We strongly believe that GraphQL has all that is required to finally standardize the API world.