GraphQL to the rescue — a short introduction
GraphQL is a query language invented by Facebook and exposed to the public in 2015. Is an open specification that allows you to query APIs in a flexible and intuitive way.
We keep hearing about GraphQL and how it introduces a revolution in the way you are writing apps, and how GraphQL is better than REST or how it is REST 2.0. It’s not about being better, it’s about solving some flaws REST has, and complementing REST.
Most of us, when we’re talking about APIs, we’re referring to REST APIs, or at least wannabe REST APIs.
A short summary of REST constraints
- Client — Server — it assumes the existence of a client and a server, and the server should not be aware of the client’s existence
- Stateless — the server keeps no trace, no identifier at all, and if there is a trace, that is contained in the request. The server treats every request as a new one, having no history
- Cache
Caching is one of the most important specification of the HTTP RFC. With that it can allow a client to make as many requests as needed, but the server will not necessarily make the trip to the database to bring the same data. This is a way of instructing
4. Layered system — the client doesn’t know if it talks with a proxy or a load balancer, as long as the response is received, and it shouldn’t care
- Uniform resource
Has 4 sub-constraints
- Identification of resources — each resource should be identifiable and addressable
- Manipulation of resources through representation s — a client will never interact with a database resource, it most likely interact with a representation of a resource. That representation might be a composed representation, or a sub-representation of, for example a database entity
- Self-descriptive messages — Each request/response should contain everything necessary so that each party can be able to understand it correctly. It should contain the right HTTP Method (in the intended usage way), the correct Status Code and the right headers (for example Accept, Content-Type, or any custom header)
- HATEOAS — hypermedia as engine of application state
Assumes that the next step the clients will be able to perform will be contained in the response as a separate area.
{
"links": {
"self": { "href": "/speakers" },
"next": { "href": "/speakers?page=2" }
}
}
In other words, Roy Fielding argues that a client shouldn’t know anything about the API, except its initial URI and the appropriate media-types and verbs. This way the server will be able to understand what is asked and respond accordingly if the client includes all the necessary info in the request.
From that point on, all the application state transitions will be driven by the client-selection of the received representations from the server, or from the user’s manipulation of them.
REST, as an architectural style is very powerful, and it aims to treat everything as a perfectly addressable resource, leveraging the correct response codes, the correct HTTP Verbs and HTTP headers, while maintaining no trace whatsoever about previous request.
It aims to allow a server and a client to evolve independently and to allow the server to drive the application state by leveraging HATEOAS and hypermedia types.
Unfortunately, a good number of the APIs out there, completely ignore the HATEOAS part — under the pretext that it adds overhead to each response or that there’s no real benefit in adding it.
It might be true in some scenarios, but it also brings a lot of power if implemented correctly and it’s up to your design, to do it or not.
Issues with REST APIs
REST APIs even with their demonstrated results, tend to have 2 major problems.
- Overfetching — we struggle to be so compliant to REST and most part of the data that is transferred over the network ends up being ignored and not displayed in the UI, and it gets thrown.
- Underfetching — comes hand in hand with overfetching, and is happening when the consumer is forced to make another call to an endpoint to bring other data
Some say that overfetching is bad design, or lack of interest, and it can be avoided. It can, but you don’t always have control over the consumer app.
As soon as you expose your API to the public — to be consumed by third parties, or if the client application is developed somewhere else you pretty much lost the control over your API’s design.
You won’t be able to tell what data they use from your responses, if they use just a field, or two fields, or the entire response.
While you can do everything to expose a performant API, you can’t customize it for every possible scenario, and for any potential customer or consumer app.
GraphQL to the rescue
With GraphQL, you’ll be able to model the data you expose in a way that is very similar to a graph. You’ll have nodes of related data, that can be ‘navigated’ by your consumers.
query {
talks{
description
title
feedbacks{
comments
delivery
}
speakers{
companyName
}
}
}
This kind of request is very intuitive, and the response to such query will bring over the network only the requested data, therefore giving a lot of flexibility to potential consumers.
GraphQL allows your consumer to manipulate hierarchical data and to create queries and mutations on the fly, in the way that you define it on the server side.
One of the scenarios where GraphQL might prove its power is along with a microservices architecture.
For this, you could create a gateway-like API that will aggregate data from several APIs and, in turn will expose queries and mutations to the client apps.
This way you can allow your consumers to get only the data they need, but a degree of nesting that you see fit, all with a single call to the server.
No more subsequent calls to different endpoints, no more endpoint chaining hell, and no more endpoints! You’ll have only one endpoint used by any consumer might be out there.
Think about this as if you would like to separate the stones from the sand, and you sift the very fine sand.
What can you do with GraphQL
Queries in GraphQL
A query in GraphQL is pretty much everything that can be ‘questioned’ from the outside, allowing the consumer to specify what data it needs to be returned from the API.
Queries can be executed in in parallel, on the same call.
query {
talk(id: 1) {
description
title
speaker{
lastName
}
}
}
Mutations in GraphQL
A mutation in GraphQL is pretty much everything that changes a certain state. A POST, PUT, DELETE request, that modifies something.
Mutations will be executed sequentially, not in parallel.
mutation($talk: talkInput!) {
createTalk(talkInput: $talk) {
title
description
speakerId
}
}
Downsides of GraphQL
Although, you can’t say that GraphQL is better than REST — because these are 2 different concepts, for sure you can leverage both to get the most of your APIs, but you need to be aware of the flaws — Caching
Caching is one of the most important specification of the HTTP. We use it to improve performance, to save a trip from the web server to the database server, and we use it to trick the user that everything runs very fast.
When we’re talking about GraphQL, you’ll have a single URL where you get your data from, but that request can be made with different bodies or parameters.
Facebook started the hype, and now GitHub announced that the v4 of their API will be fully on GraphQL.
I mean, why would they do that if they can’t cache responses to improved perceived performance?
Well, they have so many clients, and so many endpoints, that it really makes sense for them to switch to GraphQL and to give their consumers the needed flexibility. In the end, they can’t tell for sure what data they use from the responses.
Simply because these giant use GraphQL, it doesn’t mean you should use it too.
You need to analyze what are your scenarios, the pro and cons, and to know exactly what’s the end goal for you. You want to just use it, you want the flexibility of it, are you willing to sacrifice caching to flexibility? Don’t just use it without a real reason.
Originally published at irinascurtu.net on April 9, 2019.
Top comments (0)