News for hackers. Stuff that matters.
Re:Why not use GraphQL? by sho on Saturday November 07, 2020 @11:02AM (#25015797)
As something of a war-weary veteran - I disagree.

It's a good instinct to be suspicious of new technology. But I have personally seen, many times, what REST APIs can grow into - unless you are very, very careful, "get user/1" can turn into god objects with every field under the sun, non-optional. I've seen `users/l` be over a megabyte with (eg) comments, friends, comments of friends, likes, likes of friends, and every other thing the front end team ever asked for. GraphQL solves that.

Yes, it can be avoided with strict, diligent design. But it often isn't. GraphQL solves the whole class of problem. And that's why I like it, despite my mistrust of "new hotness" technology.

Re:Why not use GraphQL? by 013a on Saturday November 07, 2020 @11:56AM (#25016245)
We have a `user` GraphQL type. It has 200+ fields and resolvers into other data. Fortunately, clients don't need to pull everything.

Well, within one of our frontend apps, someone wrote a "GetUser" query fragment, wrapped it in a react hook to make it easy to use, and now anytime anyone anywhere wants to get a user, even with one field, they're getting 100+ fields they don't want. Anytime someone needs a new field on a user, they don't create a new query; they just add the field to that "GetUser" query.

Now, I've told several GraphQL advocates that setup (in our local community and online), and unfailingly they balk at it. Well, you're doing GraphQL wrong, everyone makes mistakes, you should be more selective, etc etc etc. I think that's fair; being more specific sounds like a good pattern.

Except, we are not certain the performance wouldn't suffer should we move everything to more selective queries. The issue is caching. If you have ten queries each requesting one field, the cache can't saturate until after ten network requests. But, one mega query, and now the remaining nine queries can just pull from the cache. Sure, the mega query takes longer than one mini-query, but its not longer than ten mini-queries.

I only outline this to say: GraphQL is not a magic bullet. Every single thing you can do which would ruin a REST API is also possible in GraphQL. REST API responses naturally evolve into god objects. GraphQL APIs solve the god object issue server-side by saying "god objects are fine", then push the responsibility of not abusing it onto the client (and it should be obvious, the client is the worst place to solve almost every problem, but that's another topic).

GraphQL is easier and better for some things, far harder for other things. At the end of the day, its no worse than REST. I don't recommend it, but that's only just because its new; unless a new technology offers some very easy to express, tactile benefits for your business, just wait for it to mature. When you get down to it, GraphQL's benefits are definitely not tactile, but they're still there, and I think over time it will evolve into something very interesting.

Re:Why not use GraphQL? by filoleg on Saturday November 07, 2020 @04:36PM (#25019707)
I agree with your point about caching, except, i think, it is missing one important detail that makes your argument less one-sided against GraphQL.

What you described is absolutely correct, except it is only the case if we cache by query. If we cache by objects and fields, none of those issues you described become relevant, and caching by object/field (as opposed to caching by query) in general seems like a better practice imo, aside from certain very specific scenarios.

In fact, it seems like the official GraphQL docs recommend that approach as well [0].

0. https://graphql.org/learn/caching/

Re:Why not use GraphQL? by 013a on Saturday November 07, 2020 @05:25PM (#25020188)
No, its still an issue. If you have QueryA which requests User { firstName } and QueryB which requests User { lastName }, those queries both have to request their data in order for both fields to be cached.

If, instead, you have QueryC which does User { firstName, lastName }, but two usages of it (QueryC1/QueryC2), after QueryC1 requests, QueryC2 can use the cached results. This works whether you're doing Query/Operation level caching or Field/ID level caching. The former example works in neither. And QueryC is trivially faster than QueryA+QueryB because of network overhead.

This isn't necessarily an issue with GraphQL (and, I thought I was clear about this, but: I'm not against GraphQL). Its a behavior of both typical REST implementations and GraphQL. And, to be clear, GraphQL's out-of-box caching story is more powerful than any REST implementation I've seen short of hyper-engineered FAANG companies, because it enables really powerful field/ID level caching across multiple queries. But it doesn't work in this case.

The point is that its still very immature. Even the thought leaders (Apollo being the biggest one and worst offender) write these blog posts filled with Best Practices and Recommendations that often convey horrible advice and flat-out misrepresent GraphQL's actual advantages compared to REST. GraphQL solves a lot of REST's problems; it does NOT solve REST's "god-object" class of problems, like the grandparent comment suggests; and it introduces many new classes of problems that remain unsolved in the ecosystem because of how immature it is (one great example is OSI L7 inspection in many tertiary tools a typical SaaS app has. Many products like Datadog, CloudFront, AWS ALB, etc are capable of doing some really cool and powerful stuff out-of-the-box just by inspecting standard HTTP headers. REST is basically just standard HTTP; your resource is in the path, query parameters, http headers, its very standard. GraphQL is not, so many of these tools don't work out-of-box with GraphQL. People are catching up, but again, its immature).

Re:Why not use GraphQL? by filoleg on Saturday November 07, 2020 @05:46PM (#25020386)
Thanks for clarifying, I genuinely appreciate comments like this one that go into actual details, without vague fluff or generalized claims. At this point, I am fully with you on this one.
Re:Why not use GraphQL? by fiddlerwoaroof on Sunday November 08, 2020 @01:10AM (#25023504)
I wonder if this can be statically analyzed? If I have two child components that request bits of data, in theory those requests could flow up the component tree and only be triggered at the root by a component that intelligently coalesces requests: add in some logic to bucket requests by some amount (50ms/100ms) or some logic to explicitly trigger pending requests and it might allow the best of both worlds?
Re:Why not use GraphQL? by 013a on Sunday November 08, 2020 @05:51PM (#25029844)
I think any timebox-based batching strategy would effectively just trade frontend performance for backend performance. Your backend would have to deal with fewer requests, and there's always a number of "things" the backend needs to do with every request regardless of the content (e.g. check a token against a database), so fewer requests is nice. But, some components would have to wait up-to X milliseconds to get their data, and if we're talking about a network request that takes 100ms, balancing the value of X to be big enough to actually have an impact, while being small enough to not double the time it takes for some components to get data, would prove very difficult.

The backend performance you could gain is kinda spurious anyway. We're talking about N requests being coalesced into 1 mega-request; I would rather clients send me N small requests, not 1 mega-request. Horizontal scaling is easy to set up and quick to do in real-time; vertical scaling is harder.

And I think, while a solution like this is interesting in the domain of "you've got two sibling components rendered at the same time who's queries could be combined", that's not exactly the issue I described a few comments up. Caching really doesn't enter into play here; it would not be measurably faster to just issue one mega-request for one component and let the other wait for the cache (which is, in the end, what we're talking about). I mean, it saves one network request, but 90% of a network request is just waiting on IO, and if there's one thing Javascript is really good at, its sitting around and waiting. It can wait for dozens of things at a time.

The issue is more specifically surrounding two components being rendered at different times. Imagine a User Preview card which displays a user's first name; the user clicks on that card, which takes them to a new page, the User Profile, which displays both their first and last name. Short of using a God Query for the Preview which covers a broad set of common user fields, like firing a shotgun and hoping you've got the cache saturated for unknown upcoming components, this situation will take two requests. The shotgun approach is what we do, and what many companies do; it works, but its imprecise. It can hurt the performance of the leading components which pulled the short stick, if that God Query gets too big, and as an application evolves you're gonna forget to keep that God Query updated with new things you may need.

This problem is enticing because it feels like there should be a solution, and we just haven't, as a community, found it. I think GraphQL, at its core, has the capability to solve this; its not like REST which is so undefined and hazy that any solution to something super-complex like this would only work in the domain of one company's "way of doing things". I hope one day we can figure it out, because I suspect that a general, easy to use way of preemptively saturating a cache like this would be a MASSIVE performance boost to every GraphQL client that's ever been written.

Re:Why not use GraphQL? by Aeolun on Sunday November 08, 2020 @01:22AM (#25023553)
I think this is explicitly what Relay does.
Re:Why not use GraphQL? by jtsiskin on Saturday November 07, 2020 @05:20PM (#25020139)
Yes, caching is a pro FOR GraphQl, not against it.
Re:Why not use GraphQL? by s1k3s on Saturday November 07, 2020 @01:02PM (#25016911)
I disagree. Where I work (and for some reason I expect this is the case in plenty of other places), APIs don't grow into being shit because the programmer doesn't know that "returning comments on the response of GET user/1" is bad, but because their manager asks them to implement that feature as fast as possible. Given that requirement, of course the guys will just throw the comments in that already existing endpoint instead of building "GET comments?user=John", right?

I'm a big fan of the saying "complexity has to live somewhere" and I think that's exactly what GraphQL is doing: moving the complexity to another layer.

Re:Why not use GraphQL? by ldiracdelta on Saturday November 07, 2020 @11:48AM (#25016179)
My REST endpoints allow a `fields` parameter that specifies the requested fields of the endpoint. Even if you do have a huge object, you can pare it down. To get only `id` and `first_name` on a `User` endpoint, you do `.../rest/User/fields={"id"=true,"first_name"=true}` . Non-standard, but effective. The backend doesn't retrieve or send the un-needed fields.
Re:Why not use GraphQL? by sheeshkebab on Saturday November 07, 2020 @08:20PM (#25021822)
Solr had that for ages in their rest api. They even have more fancy, calculated fields someone could request.

https://lucene.apache.org/solr/guide/6_6/common-query-parame...

Re:Why not use GraphQL? by saberdancer on Saturday November 07, 2020 @04:19PM (#25019522)
And you can extend this pattern it by allowing "includes" which would signal to the backend to load and deliver the relations listed in the includes part of the query.

This alone makes it impossible to get backend to return god entities with dozens of relations without explicitly specifying them.

Re:Why not use GraphQL? by ldiracdelta on Saturday November 07, 2020 @05:53PM (#25020466)
I accomplish this with the same `?fields` query param and it is fractal. You can specify which _fields_ of the relations below the User you also want.

If `User` had `groups` and `groups` had `permissions`, then I can do:

    let results = await fetch('/rest/Users/?fields=' + JSON.stringify(
      {
        id: true,
        first_name: true,
        groups: {
          name: true,
          permissions: {
            name: true
          }
        }
      });
My system has its limitations however. It can't do relational constraints like GraphQL or renaming of fields, but it is likely the 20% that gets you 80% of the way.
Re:Why not use GraphQL? by andrewingram on Saturday November 07, 2020 @05:58PM (#25020531)
To be honest, once you can traverse relationships like this, you've basically just got GraphQL in disguise and might as well be using it. You're going to have all the same difficulties as GraphQL in making it perform well, but don't have the elegant (IMO) query language -- and lose some of the expressivity of fields/relations being able to accept arguments.
Re:Why not use GraphQL? by ldiracdelta on Saturday November 07, 2020 @07:53PM (#25021630)
Except I dont have to start with GraphQL. I can add the complexity when I need it instead of starting with complexity. Yes I finally got _one_ of the features of GraphQL, but I didn't have to swallow graphql or require everyone else to. They don't have to use the field specifier and it still looks very simple. In contrast to GraphQL.
Re:Why not use GraphQL? by ehutch79 on Saturday November 07, 2020 @03:52PM (#25019193)
This.

My endpoints also have fields that will only be sent if you specifically request them.

Re:Why not use GraphQL? by zaphirplane on Saturday November 07, 2020 @07:37PM (#25021480)
What about nested structures their fields ? You can definitely roll your own anything if the cost of the widely used solution doesn’t work for you
Re:Why not use GraphQL? by goostavos on Saturday November 07, 2020 @12:05PM (#25016320)
Meh, people have been selling "technology-X" using this exact same argument since the beginning of time. You could swap out the "GraphQL" in your final sentence for "micro-services" and it'd swear that I've seen it in another thread ^_^

The existence of a God Response / God Object / or just a generally horrific and coupled system strikes me as a particularly human induced problem which no specific technology can actually fix.

Re:Why not use GraphQL? by HeyHoJoe on Saturday November 07, 2020 @11:19AM (#25015923)
I think that’s just pretty basic bad design, to be honest.
Re:Why not use GraphQL? by diveanon on Saturday November 07, 2020 @11:23AM (#25015947)
Thats the whole point, REST facilitates and often encourages bad design.
Re:Why not use GraphQL? by berkes on Saturday November 07, 2020 @11:43AM (#25016124)
How does it encourage this, and how does graphQL discourage this?

I've always held a strict rule where The R in REST stands for Resource (which isn't true). There's a user, an Invitation (and not an invite action on user, nor a state:invited or invited_at on user). there's a Session. There's links that clients follow, and everything is as small as possible. I really don't see how REST encourages God objects.

Re:Why not use GraphQL? by diveanon on Saturday November 07, 2020 @01:27PM (#25017140)
I have seen many people try to solve the "too many requests" problem by slowing expanding rest responses into "god" objects.

GQL solves this problem elegantly by allowing you to specify the data that you need in a single request.

That is just one example, there are many many others that you can google if you are actually interested.

Re:Why not use GraphQL? by HeyHoJoe on Saturday November 07, 2020 @02:19PM (#25017887)
This is just going around in circles. “This thing is bad practise”. Ok, don’t do that thing. This is not an argument against rest or for graphql.
Re:Why not use GraphQL? by filoleg on Saturday November 07, 2020 @04:39PM (#25019745)
I think the point the parent reply is trying to make is not that you cannot follow good practices with REST and that you somehow magically get it with GraphQL. I think their point is that GraphQL makes it much easier for devs to follow good practices and with less resistance.
Re:Why not use GraphQL? by pookeh on Saturday November 07, 2020 @05:54PM (#25020481)
Put differently, Graphql gives good defaults out of the box, and REST bad defaults.
Re:Why not use GraphQL? by HeyHoJoe on Saturday November 07, 2020 @06:59PM (#25021140)
Apologies for being rude, but that’s just nonsense. What ‘good defaults’ does graphql give you?
Re:Why not use GraphQL? by dosethree on Wednesday November 11, 2020 @01:20PM (#25061080)
You can do a lot of the things that Graphql does bu just a regular old JSON HTTP API. It's just not automatic and you will have to choose your own conventions
Re:Why not use GraphQL? by pookeh on Monday November 09, 2020 @03:46AM (#25032687)
You no longer have to code data selectors explicitly for each endpoint.
Re:Why not use GraphQL? by berkes on Monday November 09, 2020 @08:14AM (#25034422)
> I have seen many people try to solve the "too many requests" problem by slowing expanding rest responses into "god" objects.

Fair point.

But I ask my question again, differently worded: how does Graphql solve this? Why does GraphQL solve "many requests" and why can't you solve or avoid this in REST.