We Ditched REST and Went with GraphQL: Here’s Why
medium.com
medium.com
For extra kicks, select one that supports GraphQL federation.
The speed of development is unmatched. Not having to do any codegen is mind blowing.
I'm looking forward to more tRPC style things that can integrate across language boundaries. I'm okay with some simple codegen to support it
It sounds a bit like Java RMI, something that cannot succeed.
In my experience, GraphQL reduces total complexity when there are a lot of backend services. That is, you are trying to stitch together a bunch of disparate things. Tools like Postgraphile really help in these cases. It’s just another server.
In other cases, GraphQL can make things much more complicated. The benefit of REST is it’s simplicity (especially if - let’s face it - you forget about all that inconvenient “representational state transfer” stuff and really it’s just GET JSON)
Like most things in life and software, there is not one true answer. The goal should be to reduce the complexity of the system as a whole, not to reject one technology because it adds complexity to one specific aspect of a system.
When you look at PostgREST REST API, you will see you can select related data, you can pick what fields, so you don't underfetch or overfetch, you don't have to create new API endpoints…
You need to add your schema to check for data validity, but that's something you'd have to do anyway.
And as you say, implementation matters a lot, we don’t feel constrained by rest at all.
I was the one to suggest GraphQL during planning, but after considering all of the parts it was clear that it would be months of additional work with too many unknowns, which isn't in the budget.
I'm a fan of GraphQL. It serves as an excellent BFF framework for performant frontends. You get types, tooling, conventions for free and if you use something like Apollo GraphQL Client, it normalizes GraphQL responses and caches the individual entities.
In addition, I realized in the last 5 years how it helped managing product teams. There were teams with die hard frontend devs that practically annoyed me every day with requests for new/changed endpoints; once I got very pi*ed, implemented a GraphQL backend and gave them the GraphiQL UI such that they could discover and query the data themselves. Saved me a lot of frustration and was fun for them.
You can theoretically do the same with REST but if you dogmatically stick to Entities-Resources, it will not be performant if you have lists with nested sub-fetch (e.g. a list of blogposts with their author and her name/avatar). If you start creating endpoints which return a whole ViewModel, you're IMHO starting to leave RESTland and if you're doing it right, will eventually re-create something GraphQL-ish.
Pushing HTML fragment updates from the server over Web Sockets and updating with morphdom seems a lot closer to young and fast growing to me.
The fastest complex JSON structure is no JSON at all.
It's very complex. Contrast it with simplicity of jsonrpc https://www.jsonrpc.org/specification
It focuses a lot of attention on result part, not so much on query input part. Contrast it with MongoDB-style querying which can be mapped to SQL as well allowing client to construct arbitrary where clauses. Trivial in jsonrpc, not possible in graphql.
Input object type doesn't allow union types, which is quite bad. It means MongoDB style queries can't be constructed - query input is rigid. Jsonrpc allows it.
There is no concept of parametric polymorphism. Jsonrpc on the other hand allows you to take advantage of type system in your programming language.
Optionality at input position is odd:
- nullable types are implicitly optional
- non-nullable types are implicitly required
This doesn't make sense.
There are apis where you'd want to:
- have parameter that is required, however may be null
- optional parameter that cannot be null - is not provided (ignore) or is provided (use)
This creates odd api where you need to allow querying by field with null value even though it's invalid (ie. optional query parameter for non nullable property).
I also can see why people criticize it for encouraging over-fetching and creating n+1 problems on the backend.
Cache times are usually short, < 5 minutes, and are cleared whenever a POST/DELETE/PUT are issued. Works pretty well in my experience.
If your baseline is so a new fetch every single time anyway, it doesn’t take much to achieve some pretty impressive wins.
I create a JavaScript object that matches the interface of my request library, axios in my case. The cache is basically a middleware to it created by function wrapping. Kind of like how memoize works but with a bit of extra smarts.
I have my own .get(), .post(), .delete() and .put() functions. So when a .get() is called, it's a cache check and return the stored value. If not found call axios.get() with the passed in args and store in cache before returning.
The post() function clears the cache then passes through the arguments to axios.post().
Etc.
The 5 minutes is accomplished with an entry on the event loop to remove said item.
It's only like 30 lines of code.
The real wins for this is in basic navigation. Clicking around site exploring, makes it snappy. Another advantage is lowering the total request count a bit to the backend, lowering the cloud bill.
Sending data to an api for creation or updating should be simple business commands and not based on resources or transport.
My mantra is to think like the business, not like an API or data store.
Some data flows end up with dependencies you don't know when you build a query. Such as a auth token, credentials, etc. So you end up with several round trips anyway for these cases.
A lot of the advantages to GraphQL don't materialize due to how front ends are built. It encourages the use of a global store to shove all data into from the large query you just completed. Except every front end I've ever worked on that used GraphQL basically used it just like REST with a few extra features because typical front end architecture encourages this. Taking little advantage of what GraphQL is suppose to offer.
In my experience versioning was more painful with GraphQL than it was with REST. With REST you know you just need to rev the path or some other obvious marker like a header, which allows you to run both versions side by side. In GraphQL this isn't so obvious that you need to do the same kind of separation for braking changes. And breaking changes are occasionally needed contrary to what some people believe.
So when I make a backend now, it's vanilla REST without anything fancy. I favor simplicity.
The tldr is that most comparisons of GraphQL, REST tRPC and whatnot don't mention Fragments and Relay because a lot of developers don't understand the purpose and value of Fragments. Per-component data dependencies, data masking, persisted operations just to name a few.
Not every application needs these features, which is fine, but if you don't leverage GraphQL to the fullest, why add the complexity and not just go with something simpler like tRPC.
On the other hand, there are backend for frontend frameworks like WunderGraph (https://WunderGraph.com) that take the advantage of GraphQL, but combine it with the simplicity of RPC. (Shameless plug, I'm the founder)
That said, I think a lot of people overuse or misuse GraphQL in situations where it doesn't really add much value. E.g. when exposing an API to third parties, our API is probably consumed by a backend. What really is the benefit of using GraphQL in this case? Wouldn't an OpenAPI/REST API be much easier to adopt for your users?
GraphQL really shines when used as a first party API from the frontend, with a client like Relay that embraces Fragments. Everything else to me is hype driven development. my2c