GraphQL is quickly moving to one of my least favorite technologies
twitter.com
twitter.com
I've put GraphQL in front of TB-scale data sources with X00,000 tables, and it was clear that (a) GraphQL wasn't designed for anything that big, and (b) if we could get it there, it would be transformational.
This is why I built Trustfall[0]: a system that keeps the elegant GraphQL syntax, and tweaks the semantics to ensure great performance and better expressiveness: left joins / recursion / aggregations / arbitrary filters etc. Trustfall flips the proposition around: acknowledge we're wrapping a database around every data source (API server / database / filesystem / ML etc.) and make it the best possible database it could be.
I gave a talk on it titled "How to Query (Almost) Everything" at the HYTRADBOI'22 conference: https://www.hytradboi.com/2022/how-to-query-almost-everythin...
I also recently used it to build cargo-semver-checks[1], a semver linter for Rust crates where each semver rule is implemented as a query using Trustfall's GraphQL + custom directives syntax.
I suspect that front-end people like it because it requires less thinking on their part. A GraphQL call can replace a bunch of REST calls, and they don't have to deal with error handling and networking which in the front-end can be really difficult. Pushing that to the back-end makes their lives easier.
I've found that on the back-end GraphQL is more work than REST, because there's a bunch of extra crap you have to do to essentially do the same thing as REST.
And there's a bunch of stuff that's deliberately undefined, like "what do you do if there's a partial failure of your calls?"
If you are hand-crafting interdependent query logic to resolve GraphQL queries from multiple sources and doing that at scale, you may want to look at db adapters and the federation pattern.
Also, GraphQL absolutely still requires error handling in the frontend, and many clients actually provide great facilities for error handling: retrying failed requests, refreshing auth tokens transparently on received auth errors, network state detection, offline functionalities, etc.
I've put a couple GraphQL services into production and have similar thoughts.
What suprised me most were the range of views from colleagues when they needed to integrate into one of their products. Some people were happy to work with something new, while others didn't appreciate the tax involved with the learning curve.
That said, I published an app that auto-provisions a CRUD service in GraphQL. So while I may not use it for most apps, I use this for general data-access.
But once other teams started integrating -- we heard all kinds of feedback.
My thoughts afterward were simply that people under the time pressure to push features daily had different appetites for any friction in their workflow.
We considered the feedback from the larger team and intentionally added support for both REST & GraphQL in our next app. We wanted to support anyone that wanted some exposure to it without forcing anyone. And that had much better feedback from consumers.
curl https://example.com/some/endpoint?someq=yup
versus curl -d '{"query":"query Q { someMethod(someArg: \"someValue\") { ...ohgawd } }"}' https://example.com/graphql
even typing that out I had to carefully count back the closing bracesAnd, from the JS PoV, similar burden of the "interior" language
fetch("https://example.com/graphql", {method: "POST", body: "query Q { #and the rest }"})Besides, any sane developer will build an abstraction on top of the fetch request.
The difference to any other JSON reply is minimal.
On the BE it's not great, harder to reason about than REST and harder to manage. It's also harder to monitor than traditional REST, since REST makes use of a full range of http header codes (the graphql server we used only used http header 200 by default, we have modified this).
What I recently learned is that the apollo client has support for REST APIs, this is a path that seems interesting to me. We've also been looking at FE libraries for REST that have similar interfaces to the apollo client, if you have suggestions please let me know.
If you have an OpenAPI spec of your REST API you can auto-generate a react-query based frontend client with Orval[2]. Works pretty well, but probably takes a bit more time to set up.
One thing I like about the apollo client is that it handles a lot of the cache invalidation for you, where as react-query it seems to be a bit more of a manual process, how are you and your team handling cache invalidation?
Also, the idea that we can just 'go back' is silly.
> GraphQL solves the rough edges of REST that didn’t exist in RPC. Just go back to RPC. Still works great, and now we have modern frameworks like gRPC that make it a joy to use.
Of course, code generation has its own particular set of gotchas and problems (for example, you really don’t want to expose the full functionality of, say, the Prisma api to the world)
Here's a non-exhaustive list:
- Kotlin: Netflix's "DGS" (https://github.com/Netflix/dgs-framework)
- Python: Strawberry (https://github.com/strawberry-graphql/strawberry)
- .NET: HotChocolate (https://github.com/ChilliCream/hotchocolate)
- Rust: async-graphql (https://github.com/async-graphql/async-graphql)
- Java: GraphQL-Java (https://github.com/graphql-java/graphql-java)
- Scala 2: Sangria (https://github.com/sangria-graphql/sangria)
- Scala 3: Caliban (https://github.com/ghostdogpr/caliban)
There's pitiful tooling for something like JSON-RPC and no equivalent of OpenAPI for it.
If you use gRPC, there's still less tooling than there is for GraphQL and the primary transport is Protobuf.
Being able to make JSON HTTP requests ("JSON-Transcoding") is a second-class citizen if even supported at all by your server library.
Seems this particular twitterer made the mistake of trying to implement their own GraphQL server from the ground up. Never do that! There are ready-made servers with neat resolver patterns which allow you to respond to queries with well defined entities while fetching their fields from any source.
That said, never do that, either! There are ready-made GraphQL adapters available for pretty much any database, and there are some very promising ”GraphQL-native” databases out there too!
And then there is Prisma, which is a one-stop shop for all your app’s GraphQL needs, whatever the database.
I’ve looked a couple times and didn’t find anything.
DGS isn't a terrible place to start, if you're already in the Spring ecosystem https://github.com/Netflix/dgs-framework#readme
There's an "awesome" list in the graphql-java org, too: https://github.com/graphql-java/awesome-graphql-java#readme
https://www.apollographql.com/docs/federation/supported-subg...