Hacker News new | ask | show | jobs
by ergothus 2766 days ago
I haven't yet had much luck in finding a GraphQL review that addresses my general concerns (I'm frontend).

1) GraphQL almost always means everything is POST, removing CDN and browser caching of GET-like requests is gone (and ServiceWorker caching just got much more complicated, nigh-impossible if CORS is involved). Everyone says "oh, clients can do better caching", as if that's not true without GraphQL. Still, the caching I mention might be trivial and mostly worthless. I'd just like to see some actual inspection of the issue.

2) The models I've seen work well if your frontend is largely a thin skin over the services with minimal business logic of their own. (this isn't GraphQL directly, but the client libs that use it, but those exist because talking GraphQL without them is more effort). Which is, of course, what we really want. Business logic in the front end is always a painful idea. But it also definitely happens, for real business reasons - are we making those cases harder? How much so? With REST we have a lot more flexibility, it seems, even if we choose to avoid using most of it.

7 comments

The caching story in GraphQL sucks. Its pretty good with frontend frameworks like Apollo, but that's not a solution to the whole problem. Sure it works for your website/app (if you've got one), but it does nothing to offer caching for a generic API.

Its easy to argue that the main advantage of GraphQL is to reduce overfetching fields on the data you need for your views. That's a great advantage. But how much of the performance advantage gained from this is offset by the substantially reduced backend cacheability of these requests? I would guess a ton, especially with highly complex views that require lots of database pulls.

That isn't to say simple caching strategies aren't still possible (you can encode GraphQL requests into GETs and just cache that url at the CDN layer, this is part of the spec AFAIK). But when you have an open API serving many users, where you can't predict what fields they're going to ask for (or even the ORDERING of those fields in their request, which would change the request body despite the response being the same!), this has to be a problem that crops up pretty quick.

There's no HTTP-level solution to this. I doubt there's any solution that would work well enough to be worth implementing. Which leads me to believe that its an intrinsic problem in GraphQL; the more freedom you give clients to request whatever they want, the harder it becomes to guarantee performance for the requests they're making. And GraphQL gives clients all the freedom in the world.

Oh, and don't even get me started about the fact that because GraphQL stitches together essentially depth-unlimited data from your data graph in one request, there's no way to express different TTLs on each item returned, on the backend or the frontend. If you've got data that could TTL for 24 hours, but another piece of data that TTLs for 60 seconds, you essentially have to specify the cache-control to account for the smallest TTL.

Overall, I think GraphQL is fine. But I also believe what we'll slowly discover is that "Company X" simply fucked up their REST API, then will look to GraphQL to solve all their problems. And it might solve some of them, but then they'll have an even more complex system in place with even harder problems. Facebook can solve those problems; us small shops can't. Better hope Facebook shares their solutions with the world.

Case in point, from the article:

> Any API change had to be deployed simultaneously to all services using that API to avoid downtime, which often went wrong and resulted in long release cycles.

There’s an easy solution to that problem, which is a versioned API.

Is it easy? Multiple api versions can be pretty annoying / tedious
>Overall, I think GraphQL is fine. But I also believe what we'll slowly discover is that "Company X" simply fucked up their REST API, then will look to GraphQL to solve all their problems. And it might solve some of them, but then they'll have an even more complex system in place with even harder problems.

This! So very much this!

I wonder if the solution is going to be to run the GraphQL resolvers at the edge so that they can make use of cached http requests. Doesn’t solve client side caching but it should be pretty good for making the most of CDNs.
I had similar concerns but have sense become a big convert of GraphQL.

1. Browser caching is replaced by the graphql library (at least in the case of Apollo which is what I've used most). Which, as far as I've seen, is a fine one to one replacement in a lot of cases because it's still an in-memory cache that doesn't hit the network. Except it's even smarter than caching based on url and Cache-Control headers and such, because it can deeply introspect the payload and is able to return a cached version sometimes even if it hasn't made the exact same request before.

You're right that you don't get caching between sessions and won't automatically get CDN caching. It hasn't been a problem for me, and to be honest I don't know that I've ever worked on an app that had a whole lot of static data payloads where caching them at this level is critical for performance. For any kind of dynamic data that's unique per user you don't really need it. Things like cdn caching of images and js and css bundles and such still work just fine obviously. But I'd be surprised if there's no way to handle the CDN case in graphql. You can probably configure the client to do queries over GET and mutations over POST, though not sure offhand that that's gonna be the best way.

One similar issue, is things like the browser network tab become a little harder to deal with. But so far I've found the GraphQL developer tools are good enough to more than offset these limitations.

2. If anything, I think it's actually easier to err in the opposite direction, i.e. have your backend be a a thin wrapper, because you can let frameworks basically auto-map your ORM to GraphQL and then write all your business logic on the frontend. But ultimately it's really just as flexible as REST, and up to you to develop your own patterns for how much logic to put in the frontend vs backend.

Basically, the downsides that I've run into so far have been surprisingly few, and in return you get strong typing of your API layer, plus depending on your client you get a lot of really cool normalizing and de-duping in your frontend store for free. That latter part is probably the biggest game changer IMO.

Point 1 wasn't a problem for adopting GraphQL for us because our end-points are very dynamic so we set no-cache headers on everything anyway. That said, clients like Apollo will let you issue GET requests instead of POSTs for queries if you prefer.

In regards to point 2: GraphQL definitely doesn't make it harder to implement front-end logic. I'm not sure how to back up this claim because it's not apparent to me why one would think that GraphQL complicates this.

I have no skin in this game, but...

1) This is more of a client implementation issue than a GraphQL issue; there's nothing about the GraphQL spec that mentions what HTTP method to use. Most people use POST because it makes the most sense in the general case but there's no reason you can't move the query from a POST body to a GET query string.

2) This question seems odd to me. The real win from GraphQL is a reduction in overfetching - if you're tailoring a REST endpoint specifically to your needs the response should be functionally identical to a GraphQL response (i.e. only the data you need). These are just paradigms for passing data - the one you choose shouldn't have much impact on how said data is used.

”there's no reason you can't move the query from a POST body to a GET query string.”

There’s disagreement on whether it is within the http spec (https://stackoverflow.com/questions/978061/http-get-with-req...), but you can also send a body with a GET request, and you wouldn’t be alone in that; Elastic uses it, too (https://www.elastic.co/guide/en/elasticsearch/reference/curr...)

Yeah, I originally was going to put that into my reply but I figured talking about the fact that GET bodies are technically doable would open its own can of worms.
well you do not need a request body, you can actually put a json string into a get query string.

something like: example.com?body=%7B%22hello%22%3A%22world%22%7D

it's wierd, but I've seen that a lot.

1) Not true. GraphQL can work with GET and you can have cached queries (to avoid the query string length).

This means, you can cache and you can do whatever you want with caching rules (source: We are running it in production for a long time)

2) This is largely up to you. You can have it as a thin skin or you can rely more on your server side logic.

For us, we chose to have the frontend only handle presentation logic, the rest is handled on the server side.

For example, a lot of our stuff relied heavily on ACL, the frontend needs to expect to NOT get any data on specific fields, that's the only responsible for it. The rest is on the server side.

> GraphQL can work with GET

So I've heard, which is why I chose my wording carefully. Does anyone actually do that?

Apollo has a persisted queries option. And there's a PR open on relay modern for it. At least for queries, both of these let's you store the query itself on the server then use a GET request with a query hash and variables.

We use this at First Look Media on some of our sites.

Yes, we do [1]

We use GET for queries and POST for mutations. Though we are not caching our GETs atm.

[1] https://functional.works-hub.com

1. can be addressed with persisted queries. Apollo has this option: https://blog.apollographql.com/persisted-graphql-queries-wit...

and Relay Modern has a PR open for it.

Doing something similar without one of these graphql client libraries shouldn't be too tough.

2) Why do you think you can't do frontend business logic using GraphQL? It is going to be exactly the same as doing it with REST.
I apparently failed to make this clear - it's not GraphQL that causes that, but the libraries to use it on the front end (e.g. Apollo). These allow for front end logic, but it does NOT read as a simple case - you appear to be swimming upstream to do that. (Disclaimer: I've not used any such library myself. I've talked with GraphQL directly, which was definitely a bit more convoluted than REST directly, which is why people like libraries to streamline that).

The second point I apparently failed to convey is that these are CONCERNS of mine, not conclusions. I'm looking to find reviews that explore these so I can reach (preliminary) conclusions, but so far I largely see one-line reassurances. Which are great, and I appreciate it, but they don't leave me feeling like I've really done my due diligence on my concern.