34 comments

[ 2.7 ms ] story [ 77.9 ms ] thread
I apprecciate the article, my own experiences have been dismall. GraphQL seems like a boon but in my experiences ends up being slow, overly complicated and extremely hard to read.

May be me though

GraphQL is an abysmal technology.

In terms of destructive power to the software industry it's almost on the level of OOP. The one positive seems to be that engineers are catching on to this fact at a much faster rate(5-10 years instead of 10-20). However, unfortunately, GraphQL sits in a position of the software stack that's very difficult to swap out, so even when engineers do realize the damage, they are stuck with it unless they change jobs. Extremely frustrating. Yes I'm one of those stuck engineers.

And then you have articles like this still touting it as some kind of rainbow miracle.

I'm not even going to list the countless issues you will be encountering by committing to this tech, or the fact that the mitigation of those issues will result in essentially gravitating back to REST with several unnecessary and convoluted translation layers. Instead, I invite you to research how Meta, the company behind the technology, is using the technology in practice. Just open Facebook and look at the /graphql queries, or read some articles by Meta engineers.

Could you explain a little more about the Meta part and how they're using it?
They don't have a "hard" persistence layer, it's all in-memory, which is the only reason they can have any sort of performance.

In terms of the actual queries, you'll find a bunch of prefetch calls and dumping of all data related to your user. So much for "fetch what you need".

What you will also find is, surprise surprise, not actually a whole lot of graphql queries. Instead, a bunch of plain REST-ish queries, custom WS, and some graphql.

I'm not sure exactly what GP is referring to, but it might be things like this?

> Facebook report they maintain an allow-list of queries extracted from from their source code at build time, to fix this. I've not seen any other GraphQL site do this

https://x.com/AdamChainz/status/1392162996844212232

Which references this article: https://intercoolerjs.org/2016/02/17/api-churn-vs-security.h...

It was beautiful before they did this. You could introspect the entire Instagram API surface and write queries to scrape precisely what you wanted.
This, to me, doesn't sound believable, as conceptually, it such a trivial problem, that I don't believe Meta can not handle it. Maybe in 2016 when that article was written that was the case, but even then I doubt it.

Yes, for your average small team that hasn't figured out how to do resource- and subresource-level permissions, this will be tricky. That will also be tricky regardless of whether you are using GraphQL or REST (though with REST, the "solution" is often to write permission checks on a more coarse level and hope that they align correctly with the data you are querying).

However with the advent of Zanzibar and derivative solution and policy languages (Rego for OPA or Polar for Oso), it has gotten quite easy to do (sub)resource permissions without that being a huge burden on complexity and your codebase.

It is trivial to verify Meta is doing this. If you go to Facebook or Instagram and look at the network traffic, you might find requests to /api/graphql, with a lot of weird values in the request payload, but no GraphQL query text — one of the fields is an ID of the query from the allowlist, and GraphQL becomes a glorified RPC mechanism.
I'm not disputing that Meta is doing build-time query->query ID replacement. I'm disputing the that they are doing that(/have to do that) because it's the only way to satisfy security requirements.

It makes sense for many more reasons to do that, e.g. to validate/automatically optimize your database schema and indices. Especially if your base database is quite schemaless (such as the TAO system, which they used for a long time), that can be crucial for performance.

My experience has been that it falls into the category of making easy things hard. I had a previous team that adopted it, and it turned into a huge time sink. These days, I'm just using PostgREST, and life feels easy again.
Could you or someone else expand on the destructiveness of OOP to the industry?
It is not as easy to see as with GraphQL because the term is overloaded/ill defined, and there is a large number of ways to interpret how OOP should be used. Probably why it took so long to realize the issues and move away from the concepts.

Sidenote: with GraphQL you will also see a lot of people who are scratching their heads saying "Surely I must be doing something wrong, it can't be this bad. I just don't understand what that something is.". When the users of your tech have difficulty even articulating what the issues are, that's when you know you hit the anti-design jackpot.

In terms of whether a shift away from OOP has happened, you can look at how modern languages/language features are designed, and how "best practice" has changed: they are explicitly moving towards data-centric design with FP concepts(e.g. ADTs, "plain" functions, ironically similar to C), and moving away from dynamic dispatch. And when they do implement dynamic dispatch, there are warning signs around it, it's not considered good practice (see e.g. trait objects in Rust). Encapsulation/visibility is now treated as an orthogonal concept (as it should be), the whole getters/setters visitor-pattern/proxy-pattern/etc nonsense is essentially binned, they're not even mentioned anymore outside legacy codebases and Java shops.

In terms of what the issues are, it's inheritance/subtyping and dynamic dispatch, IMHO the two hallmarks of OOP. (I know, purists will point to a different kind of definition, but in my experience this is how OOP is used in practice). There are some additional oddities like "design patterns" and "encapsulation" and whatnot, but I would consider these as secondary fallout issues, stemming from the two major problems and a zealous shoehorn-y attitude. This attitude BTW is characteristic of hype waves.

Ok so what are the issues with inheritance?

From a type-theoretic point of view it's variance. When you have a (parametric) polymorphic type and you shove a type into it with subtyping relations, you'll get problems. The classic example is the array of Animals/Dogs/Cats case. At the time of the OOP hype's peak, advocates kept bringing up this example as if it was a tool to understand OOP better. But instead, it's a great tool to understand how subtyping can lead to intractable reasoning about variance for no good reason. "Composition over inheritance" is now commonly understood as a good preemptive tactic. (Composition is not an OOP concept.) From a data-structure point of view the issue is fields. Can/should a subtype access the parent's fields? How about multiple inheritance? Throw in the private/protected/public trio and you'll get pieces of code so hairy that you'll just end up writing wrappers around it instead of trying to understand it.

Sidenote: I do want to note that there is a single use case of inheritance I know of which actually makes sense, but it's very specific to C++. It's "plain" (non-virtual) inheritance for the purpose of composing memory layouts while still allowing pointer aliasing. Row polymorphism (see e.g. TypeScript) is also useful, but it's difficult to argue that it's an OOP concept.

Ok, what are the issues with dynamic dispatch?

From a code design point of view the issue is, for lack of a better expression, missing alternatives. OOP-supporting languages "solved away" ADT-style dispatch (enum data structures+pattern matching) which has a very natural mental model, and replaced it with things like double dispatch and code-data coupling. When I'm writing a piece of Java code and I want to express that there are 3 known states that the data can be in, I have no choice but to use an abstract State class, add dynamic dispatch and either tightly couple the state-handler code with the state definition, or bloat the ...

Thanks for the lenghty write up, I appreciate it. Even though I write mostly Java for a living, I’ve got only a couple of years of experience and lack the means to contribute to a discussion of this level of expertice.
I mean sure you can devote some time to building a decent GraphQL schema, but will it really be worth the time/effort/investment when you can hack a painless REST API that can do all those dead simple CRUD operations easily?

Everything you described from posting jobs to searching candidates are dead simple POST and GET requests. No need to overcomplicate things…

Graphql adds an extra layer between client and server. You may gain some benefits, but you get extra complexity and some performance punishment as well.
I've developed one thing that uses a GraphQL API and crying is definitely what I wanted to do. Why is it my job to dig through your schema to get a response that would be just a simple GET request or two with a REST API?
GraphQL is their business, so take this article with a grain of salt, it's not objective at all. It's on their best interest to promote GraphQL.
Where's the "crying" part? The GraphQL schema designed in this article is very trivial, nothing beyond a "hello world" level. There are no advantages to using GraphQL here, and many well-known disadvantages of using it anywhere. A REST API can have an endpoint that returns companies and their job postings, everything shown here can be trivially done in REST. And of course, there is nothing about how to actually implement it on the backend in a performant way.
GraphQL doesn't solve engineering problems it solves human problems. It's a mechanism to patch bad employee communication
Stating this alternatively, it removes the need for coordination and communication and allows teams to work independently. Which is good.
Yawn. GraphSQL company promotes their blog. How does this make the front page?
After a lot of crying no longer using GraphQL, just REST API-s
I see a lot of negativity in this thread about GraphQL. As someone that's gonna be building a backend API soon, what's your favourite article/guide to build a REST API at scale assuming that GraphQL is overly complicated for our use case? I'm probably going to have to explain the main differences or at least contribute my own opinion so any link would be appreciated.

We mainly use python and we're probably stuck with MSSQL. I've built simple stuff with FastAPI and even Flask before but nothing serious.

The best recommendation I can give is to pick a standard like JSON:API, and stick to it. Not to make the standard wonks happy, but to save your team from discussions on how to structure a given response. Less bike shedding, essentially.
You don't need GraphQL for the same reasons you do not need to sync your state between the client and the backend, everything can be done with htmx and one source of truth for the state.
Despite my preference for it, I've become convinced that REST/Hypermedia is too hard of a concept for 2024-era development.

It requires a deep understanding of many ideas and people aren't able to grasp what it means and what it solves (hint: it is not meant to solve schema design). It ends up being a problem instead of a solution.

GraphQL (which is built upon REST, but has a simpler conceptual load) is way better for common everyday webdevelopment.

Has anybody used GraphQL for Data Science access?

As a strong DDD advocate, the core idea of GraphQL makes me scream on the inside. It turns explicit FE/BE contracts into implicit ones and you lose out on valuable domain insight.

However, if you have a purely read-only use-case with no way back to the BE, then maybe it's a nice tool actually? Especially since Data Guys often lament not having access to the full DB and making specific endpoints for them get tedious really quickly.

>Especially since Data Guys often lament not having access to the full DB and making specific endpoints for them get tedious really quickly.

Are the data guys in charge of the DB performance? Because if you give them GraphQL access, they are essentially going to be.

Of course you need to define some play-rules first. You could also just give them access to a read-only replication/cache.
I'd much rather have specifically designed API endpoints that I can both optimise and to also limit how much it can be accessed than rely on some other group of developers to not go overboard, especially if they're not familiar with database performance. Although if the data team owns the database, then they're free to break their own toy as far as I'm concerned.
That was the idea. You give them a copy of your actual DB, which is held up-to-date on a best-effort basis. If they break it, or it is too slow, it's on them.

When it comes to changes of the DB schema, you must inform them but they ultimately act as conformists rather than having a Consumer/Producer relationship (which is the only way GraphQL can work imho).