Performance, security, actually building a GraphQL server. What else have you encountered?
Graphql is a typical example of something that is nice on paper but doesn't pass the reality check.
Otherwise, yes, it's not better than REST.
Unless you have hundreds or thousands of developers consuming an API endpoint, it’s generally better to build the API tailor specifically for each screen/ use cases/… you have. When thinking about API that way, the value of graphql is not that clear anymore
Graphql is really suited for aggregating disparate data sources and making them look unified. You dont need to use ot that way, but that is the main value prop.
The downsides that killed it for us was that performance characteristics seemed less clear, and ever replacing it would be a nightmare due to its unstructured usage.
Things that were simple in REST (like rate limiting, capacity planning, authorization) seemed more difficult, and we didn't need the killer feature of it.
It is an interesting tech, but you are probably better off starting with REST and adopt gql on top afterward if you need it.
But the reality is that it is often more costly to parse exactly what the client want and have graphql retrieve the whole data and decimate just the needed fields. And you don't even save bandwidth because a lot of metadata had to be transferred to do that.
In a similar way, you will do one request, and the graphql server will have to trigger n requests to internal services. Then you have things like having to wait for the slower service to be able to reply and display anything to the user, also having to still send n internal requests even if one of the first and important one would fail, like retrieving an user account.
It will be harder to cache responses if the response content is specific to each request.
A lot of things like that, where, in the end, you see that it is a lot more easier and efficient to have the client do generic individual api requests.
For a queries and mutations you still need to write business-logic and database access which is very similar to how you would develop a REST-API.
Huge companies are slow to adopt things. All the smaller companies I've worked for used GraphQL, but even then I didn't see the benefit over a regular REST-like API.
If you're a small company where the FE and BE can work together to make the REST API function exactly how you want, it's not really a big deal. But in B2C or B2B situations where the API provider isn't working alongside the end-users, GraphQL gives the consumers WAY more freedom to choose what they want to fetch -- and no more. That query language is amazing for that use case.
I've used it to work with the Nvidia GeForce Now API, for example, which has thousands of games and dozens of parameters (which store do you want it from, whether you want images, titles, how you want it sorted and filtered, whatever). I wanted a list of all game IDs on Steam, and that is a single query in GraphQL rather than several blocks of back-and-forth REST queries plus more client-side filtering. https://ighor.medium.com/i-unlocked-nvidia-geforce-now-and-s...
Similarly, with headless CMSes like DatoCMS or Hygraph, it gives you a central place to put all your content but then consume it however you like across different frontends (web, native, syndication, whatever) with powerful and customized queries. https://www.datocms.com/docs/content-delivery-api/filtering-... https://hygraph.com/docs/api-reference/content-api/filtering
Significant engineering time will need to be spent ironing out important things that just work with REST (like caching).
The best analogy I have for what working with GraphQL on the backend is like is the “If you give a mouse a cookie” story [1].
You try to set up an API but end up being asked to implement three different caching layers, using the data loader pattern to batch requests to the DB to improve performance, discovering that custom error handling code is needed to get non 200 status codes back from your API, using persisted queries now that your frontend is asking for a lot of data in the body of the request which is taking up too much bandwidth, etc…
The code as you can imagine after doing all this is very hard to follow, even without doing any of the optimizations I listed above there are things like reference resolvers that make tracking down bugs or just finding where the data is being collected from a nightmare.
[1]: https://en.m.wikipedia.org/wiki/If_You_Give_a_Mouse_a_Cookie
I understand why GraphQL might make a lot of sense at a very large scale, but how does it add anything noticeably positive over REST to a trivial project to make up for the extra work?
https://github.com/tailcallhq/tailcall
GraphQL community is quite small and fragmented. Mostly composed of frontend engineers who are focused on improving dev-ex with APIs.
It would benefit the ecosystem, if people with a system's background or platform engineering background could get involved. Fix various aspects of performance, security and maintenance.
GraphQL pushes complexity into the backend where it’s arguably easier to manage, in return the frontend can have more flexibility and autonomy as a client.
REST pushes the complexity to the frontend requiring clients to orchestrate multiple calls, and reconcile the data models in the API to their own.
GraphQL got a lot of early praise for having good tooling that can provided end-to-end type safety, autogenerated client and server frameworks, and so on. OpenAPI has more or less caught up on this front now.
You can’t just take a REST api and convert it into a GraphQL api. Like going from dynamic to static types, with GraphQL it pays off to define your data model and reuse it throughout the API.
I’ve seen simple things like using the same field name, or same set of fields for a given type get bikeshedded for months. You can get with this for REST APIs, but not GraphQL.
Really, it's just more awkward than writing a straight-ahead REST implementation.
Also the error-handling semantics gets pushed to the backend, and the frontend team (who generally doesn't like handling errors) doesn't really know what to do with errors in general...so the UI design team needs to add that sort of error handling to the UI which makes everyone confused because usually there's nothing you can do about errors on the client side.
The error handling issue can be seen with this simple example: you federate 10 API calls, and 9 of them work fine. Do you return partial data? How do you indicate to the front end that there's partial data? What if the data in the 10th call is the one they need in the UI?
This implies that you need yet another state indicator that says "part of the data was returned" (if the destination was a field)...which is different than "that field was empty." And that's at a minimum.
You cannot satisfy both with one tool. Migrating to GraphQL (or choosing it in the first place) will frustrate consumers of it who primarily use your API for things other than writing frontend clients. Using REST will frustrate people who use your API to write frontend clients.
We did this with Strawberry in Python for backend (which uses dataclasses for defining resolvers), and TypeScript + graphql-codegen on the frontend. We have fully automated type generation from the backend to the frontend, meaning GraphQL becomes a cross-language, shared type layer. It works great, once you get everything setup. Worth the effort IMO.
Not sure about that, we have a codebase that's huge, with 100s of REST endpoints, and the backend engineers simply start writing new endpoints because frontend needs one more specific field, and the backend folks can't be bothered to refactor the codebase for an endpoint that's used elsewhere, as that takes time. GraphQL solves that cleanly by allowing the frontend to request any data they want and for the backend to focus on figuring out how to give back a piece of data if it's requested. No 100s of endpoints required.
The fact is, you still need those endpoints, it's just your developers aren't afraid to change the GraphQL endpoints because they're documented. Sometime down the line your developers will become afraid to change the GQL endpoints and you'll have the same, but different, issue.
Also tRPC rules.
The comment:
GraphQL is very useful, it removes whole classes of bugs. You can even use a Result/Either type where if you don't handle both the success and error cases, the GraphQL request won't even compile, so you can get type safety at both the client and the server while also not having to use purely TypeScript like with tRPC, allowing multiple clients like mobile and web. Pothos does this very well as an error extension [1], where, given the schema:
type Error {
message: String!
}
type Query {
hello(name: String!): QueryHelloResult
}
union QueryHelloResult = Error | QueryHelloSuccess
type QueryHelloSuccess {
data: String!
}
you can then query it with query {
hello(name: "World") {
__typename
... on Error {
message
}
... on QueryHelloSuccess {
data
}
}
}
If you forget `... on Error` the query will simply fail.I should also add that most people use GraphQL incorrectly, to get the benefits of not over/underfetching, the Relay approach using fragments is the only viable way currently. Otherwise it's not too much better than REST. You define the exact data required for a specific React component in GraphQL fragments, then the Relay compiler will stitch those fragments together into one and only one request. This is a great (if long) overview on the problems Relay solves and why everyone else uses GraphQL incorrectly (then complain that GraphQL sucks) [2]. Hint, Apollo is not the way.
[0] https://www.youtube.com/watch?v=yab6i9lrEv0