GraphQL, a query language for APIs, became very popular since it was first publicly released by Facebook in 2015. Many companies increasingly adopted GraphQL that provides a simple declarative way to retrieve data.
At Trax we started to use GraphQL over the last year. As part of the adoption process, we discussed the cost vs. value of using GraphQL in our services. While GraphQL has many advantages, it is also introduces a new set of challenges which need to be evaluated.
In this post you can find guidelines for deciding when it makes sense to use GraphQL.
“What you want is what you get”
No Over-Fetching or Under-Fetching of data:
With GraphQL, developers can fetch only what they actually need, nothing less, nothing more. No need to fetch data from large objects with a fixed structure that contain unnecessary data (Over-Fetching), or fetch relational data with multiple requests because an endpoint doesn’t return all the information required by a client (Under-Fetching).
Reduce response time and network bandwidth:
GraphQL allows making a single query request to get exactly the data we need, including relationships, from multiple resources. This means fewer network requests and round trips, which saves time and bandwidth. It also helps to save waterfall network requests, where you need to resolve dependent resources on previous requests.
Reducing complexity through abstraction:
All of the requests are sent to a single endpoint. The client side doesn’t need to worry about endpoints and the response codes.
Auto-generating API documentation:
GraphQL Playground allows API developers and consumers to explore the relationships between types across your schema in addition to getting details about individual types. GraphQL keeps documentation in sync with API changes.
Types supported by the API are specified in the schema using GraphQL Schema Definition Language (SDL), which makes GraphQL less error-prone, and more validated. GraphQL has a better relative type safeness compared to REST with documentation because the types described are enforced by the GraphQL engine.
When Should We Use GraphQL?
Common use cases of GraphQL API:
- Applications for low bandwidth devices such as mobile phones and IoT devices, where bandwidth usage matters.
- Applications where nested data needs to be fetched in a single call.
- Applications that retrieves data from multiple, different APIs.
- GraphQL as an abstraction on an existing API.
- GraphQL is particularly great for front-end development (for example: Angular, React, Mobile), since using a GraphQL client library helps eliminate many of the inconveniences and shortcomings that are experienced with REST APIs.
When shouldn’t We Use GraphQL?
Despite GraphQL’s advantages, GraphQL has implementation challenges, and is not necessarily the right solution for any use-case.
Existing REST service
If you have a stable RESTful service, there’s probably not a strong case to overwrite it all. What you might want to do is implement additional abilities using GraphQL.
One of the great benefits of GraphQL is that it’s not designed as a wholesale replacement for alternative API solutions. Instead, GraphQL can be implemented incrementally to complement or enhance existing APIs.
Overkill for small applications
While GraphQL is the right solution for multiple micro-services, a simple REST API can be better in case you have a service that exposes a really simple API\not API-centric. REST can also be a valuable approach for connecting resource-driven apps that don’t need the flexible queries offered by GraphQL. Take into consideration future needs, it might change if your app is intended to grow.
Server to Server
When the client of your API is another service (server-to-server) it may not make much sense to choose GraphQL. The investment cost might not be worth the value as most of GraphQL advantages refer to front-end clients.
Challenges That Are Worth Taking Into Consideration:
Web caching complexity
Caching helps reduce the amount of traffic to a server by keeping frequently accessed information close to the client.
In an endpoint-based API (like REST), clients can use HTTP caching to easily avoid re-fetching resources, and for identifying when two resources are the same. The URL in these APIs is a globally unique identifier that the client can leverage to build a cache. In GraphQL, though, there’s only one endpoint with many different queries, and it’s much harder to implement a caching mechanism.
GraphQL caching at the database or client level can be implemented with the Apollo clients that have caching mechanisms built in. However, GraphQL doesn’t rely on the HTTP caching methods, which enable storing the content of a request.
The problem can be partially solved by using persisted GraphQL queries that assist in producing a JSON file for mapping queries and identifiers.
GraphQL executes a separate resolver function for every field, whereas REST has one resolver per endpoint. IT means that GraphQL runs the risk of making additional round trips to the database than are necessary for requests (n+1 requests).
This is commonly solved by a batching technique, where multiple requests for data from a backend are collected over a short period of time and then dispatched in a single request to an underlying database or microservice by using a tool like Facebook’s DataLoader.
GraphQL is protocol agnostic, it means that when using GraphQL over HTTP, you’ll always get
200 OK response, whether the query was OK or not. You will have to parse the response message to know if there’s an error.
Read more - Handling errors with Apollo , GraphQL response.
The GraphQL specification does not address file uploading. You won’t have to deal with this limitation in case of REST, as there you can POST or PUT whatever content you want to.
File uploading can be implemented in several options:
- Using Base64 encoding. But it will make the request larger and expensive to encode/decode.
- Making a separate API endpoint just for this purpose.
- Using a library like Apollo for implementing the GraphQL multipart request specification.
One of the major challenges for API developers is handling updates in API contracts. In REST architecture, developers create new versions due to breaking changes in resources over time. A versioning strategy allows clients to continue using the existing API and migrate their applications to the newer API when they are ready.
With GraphQL, there is no need to maintain versions- the resource URL or address remains the same. You can add new fields and deprecate older fields. The advantage of GraphQL here is that the API consumer receives a deprecation warning when querying a deprecated field, and if he attempts to use a field or parameter you’ve removed he will get an immediate error from the server about the specific field.
Deprecating some part of an API simply at a functional level, totally changes the API consumer assumptions of what the data model is and how it behaves. Versioning helps deprecating APIs because it gives developers time to upgrade.
GraphQL gives enormous power to API consumers, which expose your API to security threats.
The most common is deeply nested queries that result in expensive computations and large JSON payloads that can disrupt your network quality. To protect your API from this kind of attack, limit query depth to block maliciously deep queries.
There are several known strategies to mitigate additional security risks, read more about this topic- GraphQL security, Protecting Your GraphQL API From Security Vulnerabilities.
Developer experience & capacity
At Trax we started to use GraphQL over the last year, but still not all developers are experienced with GraphQL best practice. When starting a new project, one of our criteria to choose whether or not using GraphQL is if we have the time and resources. This is because GraphQL implementation can take some time and make tasks more complex for developers who didn’t work with it before. As part of GraphQL adoption we did several coding workshops, with hands-on exercises, to expose our developers to GraphQL.
If you have a majority of B answers, it’s a good idea to investigate more about GraphQL for your project.
Otherwise, REST might be good enough for your case and there’s no need adding a new layer of complexity to your architecture.
GraphQL, when implemented properly, is a powerful technology that offers an elegant methodology for data retrieval and impacts both API’s provider and consumers. Having said that, choosing an API design style will have impact on the whole API lifecycle - From design and implementation to developers experience.
Therefore, when choosing to work with GraphQL, choose it because it solves a problem in a given context, knowing its strengths and weaknesses.
Did this article spark your interest? We have lots of exciting things going on at Trax! If you’re interested in learning more about how you can join the revolution of digitizing the physical world of retail, click here, and don’t forget to clap!