Recently I was asked to update a Node.JS server to replace all of the standard REST endpoints with GraphQL functionality. The project I was working on had already seen me working with multiple technologies I had never used before but this one I had never even heard of.
“It’s a query language that can function as an alternative to Rest with only one endpoint.” This was the quick summation I got when I first asked what GraphQL was. It intrigued me and I began my research.
My first concern was how this would be implemented on not just the server side but the client-side too. Well after some thorough research and an intense week of implementation on multiple platforms I have become a know-it-all on GraphQL and am prepared to tell you all about it.
What Is GraphQL?
GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.”
You may have heard of GraphQL before and gotten a few misconceptions about it so first I’m going to clear up a few things.
GraphQL is an alternative to Rest, which means you can replace almost any Rest API with it and still be able to do everything you were doing before. It’s just implemented differently because it works as a query language instead. Meaning that both the server and the client have to write out full queries to make calls to the endpoint (more on that later).
GraphQL is not a database technology. Some people think that GraphQL is just a new way to store data but that’s not true, it’s just a new way to go about grabbing the data. Any database technology you’re using will remain unaffected by your GraphQL implementation. It will allow you to both fetch and manipulate the data exactly as you can today with REST.
And potentially most importantly, it is not limited to JS technologies. There are many packages and modules out there that allow for GraphQL to be implemented on multiple platforms. I had to implement it on both Angular and Swift client side.
How is it different from REST?
On a high level, it functions the same as HTTP.
The client makes a call to an endpoint and data is either returned, edited or both. But there’s only one endpoint and the users call this endpoint by passing along a query and GraphQL uses this determine what to do.
The biggest difference is that it uses query language for its requests. This means that users specify what data they want back and how it’s formatted. No more arbitrary JSON objects that the documentation claims will be in a specific format.
A Quick Comparision (Spot the Similarities?)
- Set up Different End Points
- Map Functions to the Endpoints that handle the Data and Response
- Set up a Schema
- Define Input and Output TYpes
- Set up Different Queries
- Map Functions to the Queries tahat Handle the Data and Response
- Make Calls to the Endpoints
- Pass Data to Calls
- Handle Response from Calls
- Make Queries to an Endpoint
- Pass Data to Query
- Handles Response from Queries
Controlling the Response
The biggest difference between GraphQL and Rest is that the client can control the response. The client sends a query to the server which contains the query name, any data being sent with the query, and what data the client wants to be returned. This works by having a schema specify what data can be returned for that particular query and the user picks which parts of it they want back. There’s no limit to what data the user says he does and doesn’t want. They could ask for all of it, only the top-level properties, or a single property from object five levels deep.
It’s kind of incredible to think about returning a huge amount of data knowing the user could just pick out the few parts they need at that moment. Like only having a single endpoint to return all the articles in a database and the user grabbing the title and author. Then when the user selects an article the client makes a request with the same query and asking for all the data and filters for a specific article. Then if an update ever needed to be made for the server only one endpoint would need to be updated.
Built-in Introspect Tool
The coolest part of GraphQL, in my opinion, is the built-in Introspect Tool. By opening a webpage to the GraphQL endpoint the server will display the introspection system. This is a playground to test our queries and check the data returned to make sure everything is working. It can be disabled on the server or left on for clients to more easily learn how the server works. It also contains full documentation for the server.
Nothing makes my life easier than being able to test an API in a simple environment before implanting in my project.
The Implementation: It’s Tricky
From the client-side GraphQL setups a long and complicated POST request to the server allowing it to only need a single endpoint. To make this process simpler the client will set up a package to handle transforming the query string and variable data into the request. This is good in that it allows almost any platform to be able to connect to a GraphQL server but the implementation varies a lot from platform to platform and usually involves writing out the query as just a string that’s “hopefully” formatted correctly. A quick example of this is the Swift package because Swift is strongly typed with options and GraphQL by default potentially returns any of its values as null, all the generated return classes have optional values so they all have to go through some kind of unwrapping. If you have a lot of queries with different return types this can get to be a bit tedious.
In GraphQL the client can define what values they want to be returned from the API. When necessary a query can be updated by simply changing the response object. If it wants to keep the old version it can keep the old keys in the response and mark them deprecated. This will allow for users to be able to grab the old data or the new data within the same query. Allowing for a smoother transition during updates.
I haven’t had to use this yet since I just implemented it but I have high hopes for it.
Another cool thing about GraphQL is that it comes with a built-in caching system. No need for the client-side to set up one on their own it’s all handled for you. I quickly noticed how fast my data fetches became after the first time it loaded the data.
One big problem it can have is differentiating between new updated data and old stale data. When working on a project where the data may be changing a lot or changing only in small ways, such as checking a last updated property or a client who’s manipulating the data, this can be a problem. Even after the data is changed in the backend the client still shows the same data. Fortunately, this can be disabled if necessary but doing so is different in each package.
Should I implement it?
Should I Implement it?
- Only Uses One Endpoint
- Client Controlled Data Response
- Easy to Provide Documentation and to Test and Inspect Queries
- Available on Many Platforms including React, Angular and Swift
- Easy to Update
- Automatic Caching Included
- Learning Curve with Implementation
- GraphQL Packages must be installed to connect and each Platform Implementation is Unique
- Caching is Sensitive
- Moving Files is Difficult
The biggest difference and therefore the most mentioned selling point is that the user can control what he receives from the server in the query. It took me a while to wrap my head around why this was such a big deal. Only once in my implementation did I see an opportunity for the client to request less data then it would normally be returned when the client wanted to only list the objects returned and grab the object’s data after the user selected one. The servers I work with have a decent variety of endpoints that never return too much data and are easy to pass filters and search criteria too.
Then I finally realized that GraphQL is an answer to the problem of having too few endpoints that all return too much data. I could potentially put together a single endpoint that returned the entire contents of the database and makes my client handle parsing and filtering the data. (I have set up such an endpoint when I needed to exports the contents of the database as a JSON file) When I migrated the server I did an almost one to one conversion from endpoints to queries but in retrospect, I could have taken out a few of them and had the client just ask for specific data back.
So the big question, “Should I implement it?” Well, to be honest, I’m still not sure.
After going through all the research, implementation, and collecting all my thoughts in this article GraphQL seems equal to REST to me. It truly is just an alternative. The big points to make are REST is the current standard and has the most platform and package support and everyone has probably dealt with it and has some idea how it works. GraphQL offers a few unique features that can either make your implementation a lot better or potentially just be ignored. As I mentioned the big difference is user-controlled response and if you keep this in mind when designing your queries you could make an efficient API but that wouldn’t be any better than a REST API with well thought out endpoints and properly provided documentation. But another thing to consider is that an API that’s handling a lot of data, especially in its responses, would do the most to highlight GraphQL’s strengths.
Hope this article piqued your interest and answered some questions you had about it. At the end of the day, I enjoyed working with new technology. I may still be on the fence when it comes to choosing GraphQL or REST for my next project but it was worth checking out. If you have a new project coming up maybe try implementing GraphQL and seeing for yourself.
Want to know more about how we use developer tools?
Mobile Software Engineer
David is a native iOS developer who’s recently been working in Angular and Node. His interest in programming, love for solving puzzles, and focus on efficiency is what led him to being a mobile application developer. Although his main focus is front-end UI and API integration, he’s always willing to branch out and learn something new.