Comparing REST and GraphQL
This article will compare REST with the lesser known GraphQL style APIs.
What is a REST API?
REST (Representational State Transfer) is a client-server architecture style centred around resources and the state transitions can go through.A resource is named and located via a URI (Uniform Resource Identifier).
Usually, the HTTP transport protocol is used which give access to the standard HTTP methods/verbs allowing CRUD (create, read, update, delete) operations to be performed on the resources.
The accepted CRUD operation to HTTP verb mappings can be found here.
For instance:curl -X GET http://api.com/users/1/photos/1 -H 'Content-Type: application/json'
In the above example, the HTTP verb GET is used to indicate a read operation, the Content-Type: application/JSON header indicates the desired representation.
There are many more REST architectural constraints which would make an API truly RESTful but this is the general minimal you'll find in the industry.
Summary
REST is quite a beautiful architecture, using URI correctly to represent a hierarchical object model, using HTTP verbs and response codes as a uniform interface which is well understood in the industry, it is easy to see why it became popularised over older styles of web-services such as SOAP.Perhaps where REST falls short is in flexibility and complexity. If there are many clients requiring different data, fields from a resource the REST API is forced to return a superset of all of the data required, bloating the interface. Also as the domain model grows so does the number of endpoints required greatly increasing complexity.
Next, we will look at GraphQL and how it solves some of these limitations.
What is GraphQL?
GraphQL is a query language developed by Facebook for APIs allowing clients to declaratively query for the data it wants from a server. An example GraphQL server I implemented can be found here.GraphQL should not be confused with a graph database which is completely unrelated.
A GraphQL server is constrained by a schema written in GraphQL schema language. It defines the types (scalar, object, enumerations, collections) and the operations you can perform. Operations are split into three categories, queries, mutations and subscriptions.
fig 1. GraphQL schema including types, queries and mutations
Query requests
As the name suggests, queries are for fetching data. The schema defines query operations with a strong return type. The request can specify specific fields of the return type that it wants. This is one of the key features of GraphQL. Although not mandated to use HTTP, if used, best practices elect the GET to be used for obvious reasons.fig 2. GraphQL querying fewer fields.
Mutation requests
State changes to the API (creating, deleting, updating), are achieved via mutations. Mutations are syntactically identical to queries, in the schema and request construction. It is simply a category of operations which will have the effect of state changes. If HTTP is used, best practices suggest POST be used.fig 4. mutation request.
Subscription requests
Subscriptions allow a GraphQL server to give clients push notifications on particular events that were subscribed. Subscription requests are similarly defined in the schema as queries and mutations. Usually, this is implemented using WebSocket. Currently, this feature is not universally supported for all languages. For instance, the Node libraries do support this and the Java libraries do not.Schema introspection
GraphQL servers allow the schema to be explored via introspection requests. This is a powerful feature of GraphQL that allows clients to discover the schema. For instance, the in-browser test-client GraphiQL uses this to implement autocomplete when constructing requests.fig 5. GraphQL schema introspection request and response. Able to drill down with additional requests
Summary
At first glance, GraphQL seems to be a silver bullet that resolves all the issues REST has. It allows for great flexibility where the clients specify exactly the fields they require in the response. Why wouldn't you use this style to create your API? The devil is in the details and in the next section we will discuss the relative strengths and weaknesses of both styles of API.Comparisons
1. GraphQL good, mandatory schema (GraphQL 1- REST 0)
All GraphQL servers expose their schema in the same via introspection, always revealing all the types and operations the server can process.The schema gives development independence for front-end and back-end teams. All responses have a predictable structure and clients can continually change what fields they require so long as the object graph is full enough.
Good REST APIs may have documentation such as Swagger which gives example responses and types. However, the quality of such documentation varies greatly and may become out of date over time. Another problem is the discoverability of this documentation, it is not part of the architecture and therefore each REST API has their own way of doing it greatly slowing down integration with a REST API. Word docs, Swagger requiring basic auth, whitelisting IPs etc.
2. GraphQL good, strong return types on operations (GraphQL 2 - REST 0)
Having a known return type for all operations where what is nullable fields are explicitly defined in the schema gives clients great confidence what to expect back and how to process the response.REST APIs will arbitrarily decide what to return for particular operations. For instance, if there was a create operation that generates an ID, would you just return the ID to allow the client to make a subsequent request to read the new resource to get at all the fields? In reality, there is no correct answer to this question, different clients will suffer from either under-fetching or over-fetching of data. The API design would have to make a compromise.
3. GraphQL good, declarative queries (GraphQL 3 - REST 0)
As mentioned before a key feature of GraphQL requests is that the client specifies exact fields required from the return type of the operation. This flexibility may be particularly important for mobile with bandwidth and data limits.Another advantage is that the GraphQL endpoint is not tied to a resource and thus allows a client to get data of multiple objects in a single request. With REST the client would make multiple requests and then aggregate the responses, leading to more latency and added complexity in the clients.
4. GraphQL bad, malicious queries (GraphQL 3 - REST 1)
The declarative nature of the requests may also be seen as a disadvantage. Just as SQL can create queries that take a long time to execute so it would be possible to do the same with a GraphQL query. Given a schema with operations with enough freedom, or types with recursive structures this could negatively affect the performance of a GraphQL API or bring it down.Therefore extra measures need to be added beyond a naive API implementation to guard against this, timeouts, inventing query complexity scores etc.
REST does not suffer from this problem.
5. GraphQL bad, data retrieval complexity (GraphQL 3 - REST 2)
A naive implementation of a GraphQL API may fetch data inefficiently from a data store or a downstream service by either making repeated requests for the same data or making many small requests adding to latency when one bigger request could have sufficed.The GraphQL API implementation will have to anticipate potential usage patterns and implement an effective strategy for data retrieval.
REST APIs have endpoints with well-defined behaviour with regards to the data required to fulfil the operation, therefore data fetching can be optimised much more easily.
6. GraphQL bad, naming operations (GraphQL 3 - REST 3)
GraphQL having to invent more and more operations to satisfy the growing requirements will bloat the schema. It has swapped the proliferation of endpoints for a proliferation of operations for queries and mutations.Worst still naming operations is difficult, the quality of the API will depend on the skill of the developers at naming. GraphQL will suffer from some of the same issues as RPC and SOAP web-services had, the understandability of the API.
REST takes advantage of the URI for naming and locating a resource and using the HTTP verb to map to a CRUD operation. This uniform interface in the REST world is missing in GraphQL.
Another advantage that REST has is that every URI, resource, subresource is an opportunity for a CRUD operation, those are the only possibilities available. GraphQL requires the good judgement of the developers to invent useful operations.
7. REST good, cacheable endpoints (GraphQL 3 - REST 4)
REST read endpoints have perfect candidates for caching. In fact, this is one of the architectural constraints for an API to be truly RESTful.With the dynamic nature of GraphQL requests, this is obviously much harder to achieve.
8. REST good, per resource level (GraphQL 3 - REST 5)
Allowing GraphQL requests to return collections and to return multiple objects in a single request as mentioned in comparison 3 could be seen as a disadvantage depending on the requirements of the client. Since REST URIs are resource-centric, forcing the client to make multiple requests for multiple resources means that fail conditions are controlled by the client. Fail-fast or continue-on-fail can be implemented by the client as required. GraphQL takes this decision away from the client.There are REST APIs that offer batch functionality, potentially for a read operation but this is a muddy area that should be avoided if possible.
9. GraphQL bad queries not as powerful as you would expect for a QL (GraphQL 3 - REST 6)
It is called GraphQL as in object "graph" and "query language" for it. However, it does not offer many features you would expect in a query language, filtering, limiting, ordering that you can do as part of SQL the API developer would have to add bespoke implementations into the schema if such features are required.As an application developer, implementing such features is akin to implementing a DBMS, not the business logic you want to be concentrating your efforts on.
Conclusions
GraphQL is a very cool idea and will definitely evolve from its current state into something even more useful. Especially having operations with a return type with a predictable structure back is very nice. And also allowing the client to specify the fields required from said return type is also an amazingly powerful idea. I can see the potential for REST APIs to adopt some of these ideas.Resources
- Roy Fielding origin of REST- GraphQL
- https://github.com/kyeung2/playing-with-graphql
- GraphiQL - in-browser GraphQL IDE






Comments
Post a Comment