I think this paper misses the point. If you're a front-end developer, if you have a robust graphql endpoint available to you it's unbelievably amazing and productive.
But providing a robust graphql endpoint that is performant, scalable, secure, etc, is much more difficult than REST. GraphQL is optimizing for a different set of developers, and this paper only studied one group.
This is the strange thing about GraphQL, it shifts the work to someone else so you'll end up with people teams that benefit and teams that don't. You also need opt in from both the client and server.
I wish there was a client side library that implemented GraphQL as an abstraction over REST, GraphQL or other backend APIs. It would be nice to use some of the GraphQLs query/join features across several backend services without those services having to change. Imagine being able to merge a vendor API that can provide a tracking number with FedEx's API, for example.
There’s actually nothing server specific about GraphQL. The specification makes no mention of transport layer, it’s simply a type system + query executor.
You can pretty easily (if you have experience with the GraphQL reference implementation in JavaScript) create a GraphQL layer that sits inside of the browser, with a schema created by the UI team, that executes calls to REST APIs to resolve the data.
You could think of it as an “ORM” for the browser, which seems cool, but I wouldn’t necessarily recommend this approach (though I have done it in the past) for two reasons:
1. The “graphql” library isn’t really optimized for size so it can add a bunch of overhead to your JavaScript bundles
2. One of the benefits of GraphQL is to combine multiple requests for related data into a single query to be sent from the browser. Yes, that makes the life of the backend developer harder as they try to optimize for performance, but it makes for less data/fewer requests over the wire to the client. If you stick GraphQL in the browser, you’ve now just moved your N+1 query across the internet.
If you really want to go down that road, Apollo offers a “plugin” to their GraphQL client that allows you to call multiple REST endpoints as if they were a single GraphQL endpoint (without embedding the actual “graphql” library in the browser): https://www.apollographql.com/docs/link/links/rest/
A better approach for what you’re looking for would be to schema stitching (which allows you to combine multiple GraphQL endpoints together and treat them as one. You can even combine that with your own schema definitions to mix in whatever backend sources you want; e.g. your vendor + FedEx REST APIs): https://www.graphql-tools.com/docs/stitch-combining-schemas
Or if you don’t want to do the work yourself, check out OneGraph, which uses schema-stitching to do exactly what you describe. It’s pretty cool: https://www.onegraph.com/
I don't think #2 is that big of a deal if all requests happen async, which they should with a client side ORM, and if you're using http2.
I think the bigger problem there is how those multiple REST calls map to your data stores. Very rarely will there be clean separation of data between endpoints, and the stateless nature of REST makes it harder to optimize each call -- meaning, there will almost certainly be redundant queries.
That said, with GraphQL, your front end dev may not realize they are executing the equivalent of many REST calls, which is another problem :) I wouldn't say it's harder to optimize if you look at the application as a whole, though.
> There’s actually nothing server specific about GraphQL.
I just grokked this very recently when I was reading up on Gatsby and the fact that they use GraphQL. I was confused for a bit because Gatsby is SSG, until I realized they merely use GraphQL as a generic way to query any JSON data you might have laying around, similarly to how getStaticProps() is employed in NextJS
“ it shifts the work to someone else”
I don’t think this is specific to graphQL. I’ve seen similar patterns with (to pick a recent example) shared front end component libraries. You make something more general at the expense of increasing complexity, if you have a team dedicated to that more complex proposition and enough consumers of that system you might well benefit at an org level. but if you don’t it’s easy to get caught up supporting that complexity at greater cost in time and effort than a less general solution would require. It’s a tricky call
Gatsby does this, and I’ve built a POC that did the same thing to try to get my workplace to adopt it. I shelved it after a demo as I didn’t love the idea of maintaining a bespoke API solution. But I’m with you, I think it’s a great idea if there were a community around it.
Not necessarily on the client side, but it’s pretty common to have a GraphQL layer in between client and one or more REST (or other) APIs that does that.
I think the opposite is true. GraphQL puts most of the onus on the client to know the data model, define their own queries, understand how to join data etc. REST-style APIs do all of this on the server side, and provide the most interesting query results directly.
On the server side, assuming you have a simple CRUD service in front of a DB, you can probably use a generic GraphQL-to-DB query language library and call it a day. If you have to expose a REST API, you need to understand what's stored in the DB and create some queries, make sure they are performant etc.
Now, if you have a complex service with heterogenous data sources that you want to present homogenously, then both REST and GraphQL will be much more difficult. But even then, with GraphQL you can leave most of the hard work of figuring out how to join efficiently on the client, while with REST it's your responsibility to ensure that the requests execute in a decent amount of time.
In my own company, we use GraphQL for internal communication between a few microservices because we need the flexibility, but we expose a REST API to users, because no one wants to learn how to write queries instead of doing a simple GET on an endpoint we already expose.
> I think the opposite is true. GraphQL puts most of the onus on the client to know the data model, define their own queries, understand how to join data etc. REST-style APIs do all of this on the server side, and provide the most interesting query results directly.
This is how I view graphql (despite not having used it). It seems better practice to keep the querying done in the backend and keep frontend for display logic more than anything. Seems like graphql will encourage business logic in the frontend (my current workplace has this problem and it is not something that should be encouraged).
Well, when you say 'give me all cars and all users joined by user ID = owner id', that's business logic. With a good REST API you would just do a GET on /cars and find any user details that are needed already in each car (perhaps under a link, which may lead to the N+1 problem, but that's another discussion).
Of course, a bad REST API may expect that you do a GET /cars and GET /users and match them in your code, which is once again business logic in the front-end and bad design. There are even many DB-To-Rest libraries that encourage exactly this, unfortunately.
A good GraphQL API could also allow you to query cars and get car.Owner.Name and car.Owner.Address without you explicitly joining (the join still happens in the backend). However, I feel that many people who choose GraphQL are trying to avoid exactly this type of logic on the backend, which would explain the popularity of DB-to-GraphQL libraries.
I think if you have a small team and are developing an API for your application's needs probably things can be done as well or better in Rest, but if you have an API that needs to face to third parties or a very large organization with APIs that need to be exposed to multiple frontend teams or a product like a CMS that frontend teams that are not part of your organization then the benefits of GraphQL will often quickly outweigh Rest.
This is a feeling on the problem space, and not based on any studies though, as I'm unaware of any studies trying to determine this.
I'm in the same boat. I like integrating with graphql endpoints. But for endpoints I make myself for my own frontend, I prefer making exactly what I need. Doing it more general would be a waste of time (YAGNI etc), and since it's often the critical path (not just data fetching) it's nice to have it clearly laid ot what's happening, without having to have knowledge about how the frontend happens to call it.
Agreed with this, you definitely don't want to be the one implementing it on the backend it is no fun at all and can be quite tricky with all the n+1 you didnt see coming and all that.
The n+1 would be there with REST too. Unless you have specific, optimized REST routes - but then you can do the same with specific, optimized graphQL queries too.
REST endpoints typically return a specific set of data that you can optimize queries for. Whereas the GraphQL endpoint must handle arbitrary queries which will require some logic to prevent N+1 queries on the related tables or even resolve to other data sources.
REST endpoints typically return data I don't need. For example, the twitter REST API `/1.1/users/show.json?screen_name=twitterdev` it will show me the last tweet for the user. Presumably this involves perhaps waiting for tweet service when the client may not even want the tweet. A GraphQL client can be more explicit about what edges to select.
There are specs like jsonapi that solve this problem. I’ve never been entirely convinced that GraphQL is better than actual REST, even if it’s better than most of the APIs people call RESTful
JSON:API provides some of the same functionality as GraphQL, like specifying which fields and nested resources you want, but at that point you’re going to have the same problems with ensuring good performance with any combination of included fields and relationships.
Yes, the advantage of a GraphQL endpoint is you can ask for a variety of things and the tradeoff is potential performance issues for unforeseen queries doing N+1s or something.
If you control the API and know all the use cases for a REST endpoint, the advantage is predictable performance characteristics and the tradeoff is flexibility.
It all depends on what you need (and maybe what tools you're using to mitigate GraphQL resolver problems).
> REST endpoints typically return a specific set of data that you can optimize queries for
You mean when someone creates a REST API he magically knows in advance how it will be used and writes a bunch of specific, optimized endpoints and queries such as "/magic-endpoint/" which returns 20 blogposts with their comments?
I don't think so. And even if that were true, the same could easily be done with GraphQL.
It's not magic, you would design it in advance so you know what you're querying by and what you're returning in the payload. Typically you'd probably separate it into two endpoints `/blogposts` and `/blogposts/:id/comments`, but there are many ways to approach the problem. These days JSON:API is pretty popular for creating standard interfaces.
GraphQL allows ad-hoc queries of unlimited complexity and recursion
> If you know in advance what will be queried then you can create an optimized query for it.
No. In general you don't know what will be queried. And that's the reason why most GraphQL implementations end up using just a small predefined set of "persisted queries" (that is, REST with extra steps).
I think you misunderstand. You can write very restricted queries that mirror REST routes 1:1. No need for persisted queries.
Persisted queries enter the game when you define a query that potentially can become very complex and deep and then want to restrict the complexity in specific ways. But that is not required if you just want to mirror a RESTful API.
> You can write very restricted queries that mirror REST routes 1:1. No need for persisted queries.
What stops a frontend developer writing an ad-hoc query?
> Persisted queries enter the game when you define a query that potentially can become very complex and deep
That... That is exactly what I wrote.
---
Honestly, I'm baffled at GraphQL defenders. It's like they never even read the documentation to the tools they defend.
- How is GraphQL different from REST?
- Ad-hoc queries of unlimited complexity
- But you write restricted queries
- No. The whole point of GraphQL is ad-hoc queries
- Persisted queries enter the game when you define a query that potentially can become very complex and deep
- That is exactly what I'm saying
And elsewhere, you can see it in other replies, it's the same story with N+1:
- GraphQL is great!
- Except the issues on the server and trying to handle N+1 queries
- What's N+1?
- It's.... It's a prominent part of the documentation for the frigging tool you use. And the reason for the things you advocate like dataloaders and persisted queries
> What stops a frontend developer writing an ad-hoc query?
What stops them is that the "ad-hoc" query can only look like this:
articlesWithComments($id) {
title
contents
comment {
author
text
}
}
That's all. Now the only way to change this query is to remove fields but there is no way to make anything more complex. The only way to do more is to repeat the query. I.e. literally:
article1: articlesWithComment(1) {
title
contents
comment {
author
text
}
}
article2: articlesWithComment(2) {
title
contents
comment {
author
text
}
}
That will create two queries in the backend - that is the equivalent of just making two requests against the same REST route.
It _is_ possible to allow a user to change the query like this:
articlesWithComments($id) {
title
contents
comment {
author {
name,
age,
articles {
...
}
}
text
}
}
But that is totally optional - you don't have to give your users this power.
> What stops them is that the "ad-hoc" query can only look like this:
What is "author" in that query and why can't the user do
author {
name,
age,
articles {
...
}
}
in that query?
And what you're basically saying is: let's create REST with extra steps for no particular reason. With extremely complex setups where author in one query has a different set of fields than in a different query etc.
> I suggest you to take a step back and re-read the thread. Maybe the context got lost.
I've read the thread. And no, the context wasn't lost.
The whole point of GraphQL is flexible queries. And it is harder to make an efficient resolver in GraphQL than it is in REST.
And yes, your solution (and the solution everyone ends up arriving at) is reimplementing REST in GraphQL, poorly. Precisely because it is much harder to make an efficient resolver in GraphQL.
GraphQL unlocks Frontend-acting-as-Product, or Product
At the cost of (hopefully) a smartly written decorator, a schema-based boilerplate, or a bunch of resolvers. And surely, I guess some raw performance and enforced abstraction.
If you go the whole hog, and make your client leverage the full query granuality, then it also costs some FE complexity .e.g Apollo. But you dont always need that aspect.
Is this good for your problem space? Depends. Is it great for some problem spaces, 100%
That’s largely the point of it. Graphql allows for a smaller, more focused team to work on the generic backend and lean into the pain of it while at the same time supporting larger and more divergent frontend/user facing teams.
This comment tells me exactly what I always wanted to know about GraphQL. I'm working on a project where the front-end needs complex combinations of queries for relations between objects with various properties of different data sets. Our fairly simple REST backend with graph DB provides exactly what the front-end needs, but it does mean there's a tight coupling between the front and back ends.
So every once in a while, the question comes up whether we shouldn't be using GraphQL for this, and every time we end up unsure where to start, how to implement it, or what the actual benefits would be. We control both front and back end, and REST works fine for us.
I guess if we ever want to make our back end usable by other applications, GraphQL might become more useful to us, but until then, it seems like it's mostly a lot of extra work and complexity that we don't need.
GraphQL seems most useful when you're using something that supports it out of the box.
Good points. I had to make the GraphQL vs REST (vs maybe grpc) decision a while ago, but for my application, the API consumers are either myself (I also do the front-end) or our customers, who are not likely to be very technically proficient - for which a REST API is probably the most accessible.
Just need to figure out server-side validation now.
But providing a robust graphql endpoint that is performant, scalable, secure, etc, is much more difficult than REST. GraphQL is optimizing for a different set of developers, and this paper only studied one group.