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/
“ 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).
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.
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.
I'll be honest. I hate GraphQL. It probably makes sense in a world where everyone uses graphQL, but to me it felt like having to learn yet another query language to do what to me seems straightforward using a simple REST api.
I may also be old and cranky and you should probably get off of my lawn.
I’m 100% with you. We’ve implemented a GraphQL gateway to our REST APIs at my company, and IMO it’s been a tremendous waste of time. Tonnes of complexity, performance issues, time writing the server, monitoring problems when calls are no longer to simple endpoints, etc., for almost no tangible gain.
Also, a much more minor issue, but when everything is a POST to a single endpoint, debugging network calls in Chrome/whatever dev tools is more of a pain in the ass. It’s a lot easy browsing through GET /users/124, DELETE /messages/456, etc., and instantly see what’s happening, than having every call be POST /graphql, and have to read through all the giant post bodies to figure out what’s going on.
IMO GraphQL is no better than all the other multitude of RPC frameworks that everyone eventually realizes are a snake pits of unnecessary complexity when compared to REST. It’s just newer, so people don’t hate it as much YET.
Also the API provider had a "GraphQL is self-descriptive, go away" attitude when asked for documentation that made things worse.
It could be me (or my team), but we didn't find it easy at all to explore the API and find what we were looking for. We ended using a Python tool that generated some classes from the schema and, thanks to that, we managed to figure out the queries we needed to use in our Scala client. Not a fan.
There are definitely some cons, but I don't think the learning curve of the query language is one of them. It's simple enough that you can easily pick it up after 15 mins of reading the docs. There is also a schema proved by every server that tells you exactly what can be queried. This is much nicer than having to refer to documentation of unknown quality before you know what a REST api can provide.
Now actually implementing a server on the other hand is much more difficult.
Yeah, it just that with the use case I was exposed to (payment processing) it seemed utterly pointless and overly complex when compared to the rest API.
I don't want to query. I want to submit a transaction for processing dammit.
Again though, it might just be a case of me being old and cranky and having to learn yet another query language.
I introduced graphql a few months ago to basically unblock myself from having to think about and design gazillions of custom REST endpoints for our mobile client developers. Turns out, that I don't miss doing that. REST has been a huge drain intellectually on this industry ever since people got pedantic over Roy Fielding's thesis and insisted that we stop treating HTTP like yet another RPC mechanism. The amount of debates I've been involved in over such arcane detail as the virtues of using a PUT vs POST and exactly which is more 'correct' in what situation is beyond ridiculous. I appreciate a well designed REST API as much as anyone but for most projects where the frontend code is the single customer of the API, it's not very relevant. If you are shipping SDKs to third parties, it's a different matter of course.
In any case, we now have the graphql playground where you can prototype your queries with full autocomplete (based on the schema). I've done this with third party graphql APIs; it's stupidly easy and you don't need a lot of documentation generally.
We're using the Expedia implementation for Kotlin and Spring Boot. I have a suspicion that that setup might be lot easier to deal with than Appollo and node.js since it has the important feature of using reflection for creating the schema from code. I've not written a single line of graphql schema in nearly 6 months of creating dozens of graphql endpoints. We also use kotlinx serialization to generate cross platform parsing code in our multiplatform client (we use it on Android and in the browser and soon on IOS). So, this offloads a lot of hassle of dealing with schemas and parsing both client and server side that we used to have with REST based APIs. Maybe not the most common path but worth checking out if you are looking to get started with this stuff.
My process for adding a new endpoint:
1) write a function in a spring bean that implements the Mutation or Query marker interface. Spring Boot does the rest. It generates the schema at startup time and wires everything together.
2) start a dev server, prototype the new graphql query in the playground
3) paste the working query to a new function with a multi line string along with any model classes we need in our multiplatform (js, android, and soon ios native) client library and recompile that to add the new client code for the query.
4) update the dependency on our android and web projects (we use kotlin-js for our admin UI) to use it.
5) also add the new client to our integration test project so we can write some tests for the new endpoint. We have full end to end tests of our client and API. Our server uses some mocked databases and middleware when running the tests.
It's definitely not perfect; the Expedia implementation definitely has some quirks and limitations. Also, Kotlin multiplatform has been a bit of a moving target in the last few months (though a lot more usable as of Kotlin 1.4.x). But overall it's a great setup for a small team that has better things to do than crafting custom REST APIs.
In terms of performance, technically graphql is just an HTTP POST API on top of Spring Boot (for us at least). Yes, there's a bit of overhead for query processing on the server but most of your performance is otherwise exactly the same as it would otherwise be. You of course pay a price for crafting complicated queries. But that's the same price you pay for having poorly aligned UI and REST APIs where you end up making lots of REST calls because you did not design your API right (been there, done that). Graphql just allows you to iterate on that more easily. But it's not inherently slower in any way. We are currently not doing any federation but that's mostly because we have a monolith server instead of micro-services.
I'm with you. I've done big REST APIs and now have a big GraphQL API on my ongoing project, and I wouldn't do GraphQL again for anything I'm working on. The beneficial use cases for GraphQL are far narrower than presented, and the extra overhead compared to REST isn't worth it.
Same. But I'm also getting old and cranky. Every advantage typically pointed out over REST could easily be solved in REST. You can do joins in REST people, don't be afraid! I often would add query params for such common things, such as (fake example) fillChildren=true to have what is essentially a parent object populated with its child object in what would normally be separate calls.
Of course you can do that. But eventually keeping up with all the different fill parameters is going to catch up to you.
Besides, what do you call the parameter to fill the owner of the children? Fillchildrenowners? It’s nicer to work with if your API takes this into account.
At work almost every endpoint supports an “expand” parameter that will do various expansions of referenced resources in the returned records. This can:
- cause additional sql joins
- or pull individual records from a cache (if it’s a small enough dataset)
- or cause one additional DB query and save a network round trip.
There is one huge advantage that i don't believe REST can solve: a GraphQL server returns a schema that tells you exactly what can be queried. When using REST endpoints you are at the mercy an API's documentation, which is often quite poor. I know there are tools like Swagger that solve this problem to some extent, but its not baked into the standard like with GraphQL.
True, and this also something OData has as part of the standard. Using a standard way to do this has big benefits, as this knowledge can be implemented in tools (BI, ETL, low-code dev), which can then support many REST endpoints.
We use jsonrpc over ws on f/e-b/e and between b/e-b/e services in trading system, typescript types for api, runtime type assertion combinator library for io boundary type checks, backend teams co-maintain client libraries to access the service, it works very fast, it is safe and easy to maintain/track changes etc.
JSON-RPC is my protocol of choice as well. I feel most of these other protocols are mostly an exercise in information exchange theory which make them too idealistic, resulting in poor implementations that do not follow the standard or are extended in non-conforming ways.
In the end you simply want to interact with the client or server and procedure calls do just that. I honestly do not see the use in over complicating that.
I've used jsonsprc a few times and my experience was excellent (opposite to GraphQL, actually).
But the jsonrpc endpoint had good documentation and the client library didn't feel alien to the project, like a big query string embedded in the client code.
I wonder why jsonrpc is not used more often; but I guess compared to a REST API, the client may be more complicated.
You write the moral equivelent of __attribute__((graphql)) on your code, and boom, you can query it. You want mutations? __attribute__((graphql_root_mutation)). If your object is stored in TAO, everything works perfect. You can add custom fields or even custom objects implemented in PHP that can do whatever the hell they want.
You never have to think about a database. And you barely even have to think about security if you're using pre-existing objects, the rules for which users should be allowed to see which objects are written in one centralized place and enforced everywhere in the codebase, graphql included.
Of course, it only works that well because there are multiple ~20-30 person teams maintaining that infrastructure. And GraphQL was designed with Facebook's infrastructure in mind.
Outside of Facebook, I cannot see myself using GraphQL for any reason.
This paper has a pretty naive understanding of REST. While 'REST' can mean something different depending on who you talk to, I think in the context of a paper we can expect a bit more research.
This paper takes a typical query, and just overlays it on a CRUD-style REST endpoint, but it ignores:
* REST can definitely be strongly typed. There's OpenAPI, and JSON-Schema. In many instances I think this will work better than GraphQL, as the data you get back is more likely to follow a fixed format.
* Mutations. In GraphQL this is an RPC-style feature, whereas with the typical 'REST as CRUD' API you write in the same format you read, which can make this a lot simpler.
* Discovery. The paper discusses that REST can benefit from an 'IDE', but if you do REST well your browser is your IDE and you serve text/html as well as JSON. Ignoring good hypermedia APIs that serve multiple formats, there's also systems that let you test APIs based on for example OpenAPI schemas.
To me this is not a comparison between REST and GraphQL, but a comparison between GraphQL and a GET request on a poorly documented, low effort HTTP endpoint. To be fair, many APIs are just that.
My experience is that almost all REST APIs are like that, give or take some documentation. Though I have read about both, I have never worked with a JSON schema or Open API api. I have conservatively worked at least a hundred REST APIs, including both public and private ones.
I’m mildly optimistic about GraphQL, but without a doubt I think one of the best parts is that all GraphQL APIs have typed schemas. There is no discretion on the part of the API provider.
This is similar to a debate regarding programming languages. Some people like more restrictive languages, because they don’t trust others or themselves to reliably use good discretion in the use of powerful features or omission of optional safety checks like types.
> Some people like more restrictive languages, because they don’t trust others or themselves to reliably use good discretion in the use of powerful features
For me, it's not even that. It's that I've discovered that, even when used with discretion, the simple presence of powerful features still makes it harder to reason about how things work. Discretion around powerful features isn't a one-and-done thing; it's an ongoing process of double-checking and verifying for yourself whether that feature is being used properly every time you touch or interact with code that uses it.
A common thread in many seminal papers and essays in the history of programming languages ("Can Programming be Liberated from the Von Neumann Style", "GOTO Statement considered harmful", "Lambda: The Ultimate GOTO", to name a few.) is that, ironically enough, when you take a bird's eye look at things, reducing the power of the tools tends to increase the power of the programmer.
I should say, I'm not meaning that to be a statement in favor of static or dynamic typing; I try to stay out of that debate.[1] To me, the real problem with JSON is that, at least under typical usage, it tends to be weakly typed. (Which is a powerful feature; strong typing is a way of restricting what you can do.) JSON's type system is less expressive than that of basically any well-known programming language, including JavaScript itself, and, out of necessity, people tend to deal with that by overloading its types in ways that may force consumers to use out-of-band knowledge to interpret a message properly. This has a tendency to happen even in the presence of OpenAPI specs or JSON schemata.
Your response is to the typing nature of GraphQL, but this isn't the only strong reason for GraphQL. GraphQL reduces both response payload size to only what is necessary for the client, but also reduces round-trips.
Unless you are writing custom REST endpoints for every aspect of your UI, most formulation of what data a consumer needs will usually resolve in multiple trips to the server. So, you either scale out by having custom REST endpoints to handle each case of this (which both feels odd and presumably won't scale very well), or you take advantage of GraphQL doing this natively.
I think REST is definitely playing catch up here though. A standard gql setup generally comes out of the box with type generation, web playgrounds, etc. Of course it's possible now with REST but I really think that gql helped push the state of the art in this space.
We get that out of the box w boring old django/sqlize
we do happen to do more interesting things elsewhere (GPGPU, columnar streaming analytics, reactive frontend, ...), so like sharp edges when a 10X+ lift, but ended up backing up on this layer as it was adding complexity w immature layers vs what felt like similar perceived benefits from reliable boring stuff. it doesn't scratch all our itches, but the big ones are at a layer above/beyond graphql vs rest (eg, auth)
As someone who's worked with both approaches, at all levels of the stack (both backend and frontend), I think the paper (at least, its abstract) is missing the point.
While I do "feel" faster when working with GraphQL, I think the main benefit is that it abstracts away the busywork of transferring data between frontend and backend.
Writing a backend becomes more about describing what data is available, on what terms, how it fits together, and the operations you can do on it (mutations). Gone is the busywork of writing routes, handling CRUD in a zillion slightly different ways, etc.
On the frontend, Apollo-client lets me just write my app, not having to handle data-fetching, loading & caching for the zillionth time. I need an additional field? Just add it to the query! No need to get everyone involved.
Of course, there are traps you can easily fall into with Apollo's caching, N+1 queries on the backend, etc. But in my experience, while you do have to "drop down a level" sometimes to fix these, you spend most of your time at the "higher level".
I have the opposite experience working on the backend. GraphQL is too prone to N+1s and other inefficiencies because its in direct opposition of the way data is stored. Its much harder to make an efficient resolver than it is making an efficient REST endpoint.
Errors are harder, because HTTP codes are not used and monitoring is a lot more complicated. I see value in GraphQL - but I think it brings a lot of cost to the table.
In my experience, N+1 queries are roughly as easy to run into with naive GraphQL as with naive REST. When you are optimizing the queries, it's slightly easier to get rid of the N+1 behavior in GraphQL than in REST because you can see exactly what data the client is trying to get and can fetch data differently based on that instead of needing to come up with your own way for the API to describe what data to fetch.
This is definitely my experience, particularly in using Hasura (particularly via the wonderful NHost[0], a fantastic database service). I believe that Hasura knows how to not do N+1 queries.
As someone who has heavily used both REST and GraphQL in the past and actively, I find this comparison heavily similar to using raw HTML versus React. When it really boils down, GraphQL is just REST with types and the capability of performing multiple requests in one. Much like React is a way of creating component types from HTML elements.
GraphQL takes a bit more work to get setup and running, but it's soo worth it in the end if you value typing. One of the most impressive parts of GQL that REST isn't capable of having, is the vast tooling ecosystem enabled by a standardly typed data transfer model, the fact that anyone can write a library that can automatically hook into your model is incredibly powerful.
I find most people who have negative opinions on GraphQL simply haven't taken the dive yet to fully understand it, and they typically overthink what it actually does. In my opinion, if you're writing a progressive web/mobile app with relational data, you should hands down be using GraphQL.
well it's literally just a tree of functions with extra metadata to make it extra powerful. Also have used both REST and GQL heavily and it essentially solves lots of problems I had with REST. I'm never writing REST again and when I see that something I'm consuming also have a GQL API it makes me so happy to be able to know every single field available to me.
The only use-case where it's annoying me is a CMS for building an entire site. It's recursive as A -> B -> A -> B and the lack of recursion as of yet makes it manual work to extract every level that you need.
Does this actually pass as an academic study? It is presented in the format of a study (it looks like one) but to suggest GraphQL is better than REST based on the expenditure of effort for building out the first iteration of code for cherry picked scenarios is a first-year undergraduate CS101 study at best. Also, who funded this study?
I want to know the actual costs of GraphQL. What are the tradeoffs with REST? What are the limitations? We're not going to hear from managers who are damage controlling their decisions, but maybe the developers paying for GraphQL adoption wouldn't mind sharing grievances? Now that money and reputations are at stake, I think that unfortunately it will be a while before the tech community starts admitting to mistakes, just as was done with adopting ORMs.
The typical pitch about GraphQL is that it is intended to alleviate the pain of updating ORM dsl every time a change to an endpoint needs to be made to satisfy frontend requirements. Aren't updates to the GraphQL DSL replacing those made to the ORM? The problem hasn't been eliminated but replaced. One problem was replaced by another problem.
If the worst part about working with a REST api with raw sql calls is that you have to make a few straightforward changes, while maintaining complete control of your sql, you're doing great.
For me this is the point that I feel isn't well argued against by GraphQL proponents. Why if I'm a Javascript developer with probably a similar learning curve I couldn't just whip up a simple stateless frontend (in Node since its the same lang) and write the query in SQL? More to the point the skills learnt by doing so are more transferable. You also give your data store a chance to be more performant (e.g. better query plans for a typical DB) using that DSL to query the data store and there's a lot less complexity (components, libraries) in your solution.
Also from what I've seen the approaches that may result in single ideal query plans in your database increase the complexity of GraphQL significantly with "GraphQL to SQL" compilers which still may not give tuned SQL especially with large graphs. Reminds me of using ORM's where often the generated SQL wasn't performant/slow. Even if it does work the complexity of your solution just increased - all for what? To translate one query language into another? There's also times where it may pay NOT to expose too much of your internal domain structure to public API's which I feel from a naive developer's perspective GraphQL could encourage (direct internal API structure to contract mappings).
It feels, at least to me, that it is another abstraction layer that solves a problem that could also be solved at the org level. If there's suddenly a use case that requires a tuned query/algorithm/index as well (happens a lot from my experience) then its easy to add as a separate endpoint and test for regression test against other endpoints/use cases supported.
GraphQL specifies schema and documentation, and implementations usually come with introspection tools, which is not the case for REST. It would be more fair to compare GraphQL to something like Swagger.
That said, GraphQL libraries and tooling tend to be less fragmented and more ready to use than for equivalent REST stacks, which makes development much easier. A simple API built in Python with Graphene looks terse and declarative, while doing the same with Django REST Framework requires adding pages of plumbing code to build an equivalent REST API.
Re: GraphQL being a pain for a backend development - I don't quite understand that argument. If you want to keep a tighter control over the schema, you can have it - the API schema does not need to be a reflection of the underlying data schema with all its relationships - it should be the front-end developer's job to convince you that this or that complex relationship needs to be exposed via GraphQL and let you make sure that it's served efficiently.
This is a flawed comparison. GraphQL is probably a superior query language. The more salient question is how the complexity of back-end API endpoint implementation differs.
The answer is that it varies widely between ecosystems (i.e. you are going to have a totally different experience developing a GraphQL endpoint in PostGraphile, Graphene, and Apollo)...and the paper doesn't mention which back-end technology was used.
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.
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.
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/
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.
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).
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.
GraphQL allows (limited) queries from the client.
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%
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.
Just need to figure out server-side validation now.
I may also be old and cranky and you should probably get off of my lawn.
Also, a much more minor issue, but when everything is a POST to a single endpoint, debugging network calls in Chrome/whatever dev tools is more of a pain in the ass. It’s a lot easy browsing through GET /users/124, DELETE /messages/456, etc., and instantly see what’s happening, than having every call be POST /graphql, and have to read through all the giant post bodies to figure out what’s going on.
IMO GraphQL is no better than all the other multitude of RPC frameworks that everyone eventually realizes are a snake pits of unnecessary complexity when compared to REST. It’s just newer, so people don’t hate it as much YET.
So its relative merits have a lot to do with how complicated a thing you're trying to do in the first place.
If so, I do agree with that statement.
Also the API provider had a "GraphQL is self-descriptive, go away" attitude when asked for documentation that made things worse.
It could be me (or my team), but we didn't find it easy at all to explore the API and find what we were looking for. We ended using a Python tool that generated some classes from the schema and, thanks to that, we managed to figure out the queries we needed to use in our Scala client. Not a fan.
Now actually implementing a server on the other hand is much more difficult.
I don't want to query. I want to submit a transaction for processing dammit.
Again though, it might just be a case of me being old and cranky and having to learn yet another query language.
In any case, we now have the graphql playground where you can prototype your queries with full autocomplete (based on the schema). I've done this with third party graphql APIs; it's stupidly easy and you don't need a lot of documentation generally.
We're using the Expedia implementation for Kotlin and Spring Boot. I have a suspicion that that setup might be lot easier to deal with than Appollo and node.js since it has the important feature of using reflection for creating the schema from code. I've not written a single line of graphql schema in nearly 6 months of creating dozens of graphql endpoints. We also use kotlinx serialization to generate cross platform parsing code in our multiplatform client (we use it on Android and in the browser and soon on IOS). So, this offloads a lot of hassle of dealing with schemas and parsing both client and server side that we used to have with REST based APIs. Maybe not the most common path but worth checking out if you are looking to get started with this stuff.
My process for adding a new endpoint:
1) write a function in a spring bean that implements the Mutation or Query marker interface. Spring Boot does the rest. It generates the schema at startup time and wires everything together.
2) start a dev server, prototype the new graphql query in the playground
3) paste the working query to a new function with a multi line string along with any model classes we need in our multiplatform (js, android, and soon ios native) client library and recompile that to add the new client code for the query.
4) update the dependency on our android and web projects (we use kotlin-js for our admin UI) to use it.
5) also add the new client to our integration test project so we can write some tests for the new endpoint. We have full end to end tests of our client and API. Our server uses some mocked databases and middleware when running the tests.
It's definitely not perfect; the Expedia implementation definitely has some quirks and limitations. Also, Kotlin multiplatform has been a bit of a moving target in the last few months (though a lot more usable as of Kotlin 1.4.x). But overall it's a great setup for a small team that has better things to do than crafting custom REST APIs.
In terms of performance, technically graphql is just an HTTP POST API on top of Spring Boot (for us at least). Yes, there's a bit of overhead for query processing on the server but most of your performance is otherwise exactly the same as it would otherwise be. You of course pay a price for crafting complicated queries. But that's the same price you pay for having poorly aligned UI and REST APIs where you end up making lots of REST calls because you did not design your API right (been there, done that). Graphql just allows you to iterate on that more easily. But it's not inherently slower in any way. We are currently not doing any federation but that's mostly because we have a monolith server instead of micro-services.
It just was not difficult to learn at all.
Besides, what do you call the parameter to fill the owner of the children? Fillchildrenowners? It’s nicer to work with if your API takes this into account.
- cause additional sql joins - or pull individual records from a cache (if it’s a small enough dataset) - or cause one additional DB query and save a network round trip.
Example:
/api/v2/discussions?sort=recent&expand=insertUser,updateUser,lastCommentUser,parentCategory
This would be a pretty extensive case but is very useful.
In the end you simply want to interact with the client or server and procedure calls do just that. I honestly do not see the use in over complicating that.
But the jsonrpc endpoint had good documentation and the client library didn't feel alien to the project, like a big query string embedded in the client code.
I wonder why jsonrpc is not used more often; but I guess compared to a REST API, the client may be more complicated.
You write the moral equivelent of __attribute__((graphql)) on your code, and boom, you can query it. You want mutations? __attribute__((graphql_root_mutation)). If your object is stored in TAO, everything works perfect. You can add custom fields or even custom objects implemented in PHP that can do whatever the hell they want.
You never have to think about a database. And you barely even have to think about security if you're using pre-existing objects, the rules for which users should be allowed to see which objects are written in one centralized place and enforced everywhere in the codebase, graphql included.
Of course, it only works that well because there are multiple ~20-30 person teams maintaining that infrastructure. And GraphQL was designed with Facebook's infrastructure in mind.
Outside of Facebook, I cannot see myself using GraphQL for any reason.
This paper takes a typical query, and just overlays it on a CRUD-style REST endpoint, but it ignores:
* REST can definitely be strongly typed. There's OpenAPI, and JSON-Schema. In many instances I think this will work better than GraphQL, as the data you get back is more likely to follow a fixed format.
* Mutations. In GraphQL this is an RPC-style feature, whereas with the typical 'REST as CRUD' API you write in the same format you read, which can make this a lot simpler.
* Discovery. The paper discusses that REST can benefit from an 'IDE', but if you do REST well your browser is your IDE and you serve text/html as well as JSON. Ignoring good hypermedia APIs that serve multiple formats, there's also systems that let you test APIs based on for example OpenAPI schemas.
To me this is not a comparison between REST and GraphQL, but a comparison between GraphQL and a GET request on a poorly documented, low effort HTTP endpoint. To be fair, many APIs are just that.
My experience is that almost all REST APIs are like that, give or take some documentation. Though I have read about both, I have never worked with a JSON schema or Open API api. I have conservatively worked at least a hundred REST APIs, including both public and private ones.
I’m mildly optimistic about GraphQL, but without a doubt I think one of the best parts is that all GraphQL APIs have typed schemas. There is no discretion on the part of the API provider.
This is similar to a debate regarding programming languages. Some people like more restrictive languages, because they don’t trust others or themselves to reliably use good discretion in the use of powerful features or omission of optional safety checks like types.
For me, it's not even that. It's that I've discovered that, even when used with discretion, the simple presence of powerful features still makes it harder to reason about how things work. Discretion around powerful features isn't a one-and-done thing; it's an ongoing process of double-checking and verifying for yourself whether that feature is being used properly every time you touch or interact with code that uses it.
A common thread in many seminal papers and essays in the history of programming languages ("Can Programming be Liberated from the Von Neumann Style", "GOTO Statement considered harmful", "Lambda: The Ultimate GOTO", to name a few.) is that, ironically enough, when you take a bird's eye look at things, reducing the power of the tools tends to increase the power of the programmer.
I should say, I'm not meaning that to be a statement in favor of static or dynamic typing; I try to stay out of that debate.[1] To me, the real problem with JSON is that, at least under typical usage, it tends to be weakly typed. (Which is a powerful feature; strong typing is a way of restricting what you can do.) JSON's type system is less expressive than that of basically any well-known programming language, including JavaScript itself, and, out of necessity, people tend to deal with that by overloading its types in ways that may force consumers to use out-of-band knowledge to interpret a message properly. This has a tendency to happen even in the presence of OpenAPI specs or JSON schemata.
[1] Though I'll take this chance to link https://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wr...
Unless you are writing custom REST endpoints for every aspect of your UI, most formulation of what data a consumer needs will usually resolve in multiple trips to the server. So, you either scale out by having custom REST endpoints to handle each case of this (which both feels odd and presumably won't scale very well), or you take advantage of GraphQL doing this natively.
Wouldn't that be the normal way to implement a REST API?
In other words, as you say, if there's a schema with the REST API, GraphQL loses one of what the authors claim as a key benefit.
It's not like if there is a schema with a REST API, the GraphQL alternative becomes un-typed.
[1] https://en.wikipedia.org/wiki/Swagger_(software) [2] https://en.wikipedia.org/wiki/GraphQL
we do happen to do more interesting things elsewhere (GPGPU, columnar streaming analytics, reactive frontend, ...), so like sharp edges when a 10X+ lift, but ended up backing up on this layer as it was adding complexity w immature layers vs what felt like similar perceived benefits from reliable boring stuff. it doesn't scratch all our itches, but the big ones are at a layer above/beyond graphql vs rest (eg, auth)
While I do "feel" faster when working with GraphQL, I think the main benefit is that it abstracts away the busywork of transferring data between frontend and backend.
Writing a backend becomes more about describing what data is available, on what terms, how it fits together, and the operations you can do on it (mutations). Gone is the busywork of writing routes, handling CRUD in a zillion slightly different ways, etc.
On the frontend, Apollo-client lets me just write my app, not having to handle data-fetching, loading & caching for the zillionth time. I need an additional field? Just add it to the query! No need to get everyone involved.
Of course, there are traps you can easily fall into with Apollo's caching, N+1 queries on the backend, etc. But in my experience, while you do have to "drop down a level" sometimes to fix these, you spend most of your time at the "higher level".
Errors are harder, because HTTP codes are not used and monitoring is a lot more complicated. I see value in GraphQL - but I think it brings a lot of cost to the table.
Dead Comment
[0] https://nhost.io
Ember Data solves almost everything so you can focus on features and deliver the app in no time.
That's one thing that's great about Apollo; it's not too tied to any other tech / framework (except GraphQL, of course).
I find most people who have negative opinions on GraphQL simply haven't taken the dive yet to fully understand it, and they typically overthink what it actually does. In my opinion, if you're writing a progressive web/mobile app with relational data, you should hands down be using GraphQL.
The only use-case where it's annoying me is a CMS for building an entire site. It's recursive as A -> B -> A -> B and the lack of recursion as of yet makes it manual work to extract every level that you need.
I want to know the actual costs of GraphQL. What are the tradeoffs with REST? What are the limitations? We're not going to hear from managers who are damage controlling their decisions, but maybe the developers paying for GraphQL adoption wouldn't mind sharing grievances? Now that money and reputations are at stake, I think that unfortunately it will be a while before the tech community starts admitting to mistakes, just as was done with adopting ORMs.
The typical pitch about GraphQL is that it is intended to alleviate the pain of updating ORM dsl every time a change to an endpoint needs to be made to satisfy frontend requirements. Aren't updates to the GraphQL DSL replacing those made to the ORM? The problem hasn't been eliminated but replaced. One problem was replaced by another problem.
If the worst part about working with a REST api with raw sql calls is that you have to make a few straightforward changes, while maintaining complete control of your sql, you're doing great.
Also from what I've seen the approaches that may result in single ideal query plans in your database increase the complexity of GraphQL significantly with "GraphQL to SQL" compilers which still may not give tuned SQL especially with large graphs. Reminds me of using ORM's where often the generated SQL wasn't performant/slow. Even if it does work the complexity of your solution just increased - all for what? To translate one query language into another? There's also times where it may pay NOT to expose too much of your internal domain structure to public API's which I feel from a naive developer's perspective GraphQL could encourage (direct internal API structure to contract mappings).
It feels, at least to me, that it is another abstraction layer that solves a problem that could also be solved at the org level. If there's suddenly a use case that requires a tuned query/algorithm/index as well (happens a lot from my experience) then its easy to add as a separate endpoint and test for regression test against other endpoints/use cases supported.
Well, it was published/presented at Working IEEE/IFIP Conference on Software Architecture - https://ieeexplore.ieee.org/abstract/document/9101226 - though I have no idea on how respectable that conference is.
That said, GraphQL libraries and tooling tend to be less fragmented and more ready to use than for equivalent REST stacks, which makes development much easier. A simple API built in Python with Graphene looks terse and declarative, while doing the same with Django REST Framework requires adding pages of plumbing code to build an equivalent REST API.
Re: GraphQL being a pain for a backend development - I don't quite understand that argument. If you want to keep a tighter control over the schema, you can have it - the API schema does not need to be a reflection of the underlying data schema with all its relationships - it should be the front-end developer's job to convince you that this or that complex relationship needs to be exposed via GraphQL and let you make sure that it's served efficiently.
The answer is that it varies widely between ecosystems (i.e. you are going to have a totally different experience developing a GraphQL endpoint in PostGraphile, Graphene, and Apollo)...and the paper doesn't mention which back-end technology was used.