Most active commenters
  • GordonS(8)
  • goto11(7)
  • tomnipotent(6)
  • mixedCase(5)
  • dmitriid(4)
  • jayd16(3)

←back to thread

153 points michaelanckaert | 92 comments | | HN request time: 1.889s | source | bottom
1. WhatIsDukkha ◴[] No.23485847[source]
I don't understand the attraction to Graphql. (I do understand it if maybe you actually want the things that gRPC or Thrift etc gives you)

It seems like exactly the ORM solution/problem but even more abstract and less under control since it pushes the orm out to browser clients and the frontend devs.

ORM suffer from being at beyond arms length from the query analyzer in the database server.

https://en.wikipedia.org/wiki/Query_optimization

A query optimizer that's been tuned over decades by pretty serious people.

Bad queries, overfetching, sudden performance cliffs everywhere.

Graphql actually adds another query language on top of the normal orm problem. (Maybe the answer is that graphql is so simple by design that it has no dark corners but that seems like a matter of mathematical proof that I haven't seen alluded to).

Why is graphql not going to have exactly this problem as we see people actually start to work seriously with it?

Four or five implementations in javascript, haskell and now go. From what I could see none of them were mentioning query optimization as an aspiration.

replies(19): >>23485889 #>>23485918 #>>23485953 #>>23485962 #>>23486202 #>>23486714 #>>23486794 #>>23487403 #>>23487603 #>>23487611 #>>23487709 #>>23488354 #>>23488907 #>>23489619 #>>23489986 #>>23490334 #>>23491786 #>>23492176 #>>23497167 #
2. searchableguy ◴[] No.23485889[source]
That is upto the graphql framework and the consumers of them. Graphql is just a query language.

You need to have data loader (batching) on the backend to avoid n+1 queries and some other similar stuff with cache to improve the performance.

You also have cache and batching on the frontend usually. Apollo client (most popular graphql client in js) uses a normalized caching strategy (overkill and a pain).

For rate/abuse limiting, graphql requires a completely different approach. It's either point based on the numbers of nodes or edges you request so you can calculate the burden of the query before you execute it or deep introspection to avoid crashing your database. Query white listing is another option.

There are few other pain points you need to implement when you scale up. So yeah defo not needed if it's only a small project.

replies(1): >>23485977 #
3. kevan ◴[] No.23485918[source]
Seems like you're looking at this through the lens of a single system that could submit a query to a single database and get all the data it needs. From that perspective GraphQL is definitely an extra layer that probably doesn't make sense. But even then there's still some value in letting the client specify the shape of the the data it needs and having client SDKs (there's definitely non-GraphQL ways to achieve these too).

My impression is GraphQL starts to shine when you have multiple backend systems, probably separated based on your org chart, and the frontend team needs to stitch them together for cohesive UX. The benchmark isn't absolute performance here, it's whether it performs better than the poor mobile app making a dozen separate API calls to different backends to stitch together a view.

replies(2): >>23485970 #>>23485996 #
4. baddox ◴[] No.23485953[source]
GraphQL is quite similar to SQL. They’re both declarative languages, but GraphQL is declaring a desired data format, whereas SQL is declaring (roughly) a set of relational algebra operations to apply to a relational database. GraphQL is really nothing like an ORM beyond the fact that they are both software tools used to get data from a database. You might use an ORM to implement the GraphQL resolvers, but that’s certainly not required.

I wouldn’t expect the performance issues to be much more problematic than they would be for REST endpoints that offer similar functionality. If you’re offering a public API, then either way you’re going to need to solve for clients who are requesting too many expensive resources. If you control the client and the server, then you probably don’t need to worry about it beyond the testing of your client code you would need to do anyway.

As far as query optimization goes, that’s largely out of scope of GraphQL itself, although many server implementations offer interesting ways to fulfill GraphQL queries. Dataloader is neat, and beyond that, I believe you can do any inspection of the query request you want, so you could for example see the nested path “Publisher -> Book -> Author -> name” and decide to join all three of those tables together. I’m not aware of any tools that provide this optimization automatically, but it’s not difficult to imagine it existing for some ORMs like those in Django or Rails.

replies(2): >>23486778 #>>23491202 #
5. WhatIsDukkha ◴[] No.23485970[source]
Yeah as you say """(there's definitely non-GraphQL ways to achieve these too)."""

These are largely matter of architecture design and graphql doesn't really fix those problems (my sense is it will make those problems harder actually).

6. kabes ◴[] No.23485977[source]
"You have to calculate the burden of the query before you execute it so you don't end up crashing your database."

This sounds like disaster waiting to happen.

replies(2): >>23486024 #>>23490291 #
7. kabes ◴[] No.23485996[source]
That's indeed one of its selling points. But most products I see that adopt graphql are exactly 1 database.
replies(3): >>23486897 #>>23488883 #>>23489981 #
8. ◴[] No.23486024{3}[source]
9. dmitriid ◴[] No.23486202[source]
> I don't understand the attraction to Graphql.

It's attractive primarily to frontend developers. Instead of juggling various APIs (oftne poorly designed or underdesigned due to conflicting requirements and time constraints) you have a single entry into the system with almost any view of the data you want.

Almost no one ever talks about what a nightmare it becomes on the server-side, and how inane the implementations are. And how you have to re-do so many things from scratch, inefficiently, because you really have no control of the queries coming into the system.

My takeaway from GraphQL so far has been:

- good for frontend

- usable only for internal projects where you have full control of who has access to your system, and can't bring it down because you forgot an authorisation on a field somewhere or a protection against unlimited nested queries.

replies(3): >>23487143 #>>23487895 #>>23488435 #
10. stevenjohns ◴[] No.23486714[source]
Where I'm at now is my first foray with GraphQL - Graphene on the Django backend and Apollo on the frontend.

I'm not sure if it is the implementation - and it could very well be - but there has been more overhead and complexities than with traditionally accessed REST APIs. I can't see much value-add.

This becomes a lot more apparent when you start to include TS in the mix.

Perhaps it just wasn't a good use case.

replies(1): >>23492219 #
11. snorremd ◴[] No.23486778[source]
Hasura is one example of a graphql server that uses the SQL joins pattern to optimize graphql queries. See https://hasura.io/blog/architecture-of-a-high-performance-gr.... It automatically generates graphql queries based on your own schema and translates it to efficient postgres sql queries. The post I linked also briefly discuss the Dataloader pattern for batching graphql resolvers to avoid the N + 1 problem.
12. jayd16 ◴[] No.23486794[source]
I agree with you but I do wish for something that can improve on rest in ways GraphQL at least purports to.

Query chaining/batching and specifying a sub-selection of response data seem like solid features.

The graph schema seems to make good on some of the HATEOS promises.

I like the idea of GraphQL but the downsides have me worried.

replies(2): >>23492161 #>>23500683 #
13. square_usual ◴[] No.23486897{3}[source]
As GP said:

> But even then there's still some value in letting the client specify the shape of the the data it needs and having client SDKs

It may not exactly "shine" in those cases, but it reduces round trips and makes it easy for fronted engineers to make views that revolve around use cases instead of the resources in the database.

replies(1): >>23487839 #
14. rhlsthrm ◴[] No.23487143[source]
As a full-stack dev, I'm going to always reach for things like Hasura for building my backend from now on. It auto generates a full CRUD GraphQL API from my Postgres DB schema. Most of the backend boilerplate is eliminated this way. If I need to add additional business logic, I can use serverless functions that run between the GraphQL query from the front end and the DB operations (actions in Hasura). Most of the heavy lifting is through the front end anyways, and this keeps everything neatly in sync.
replies(3): >>23487371 #>>23487619 #>>23487728 #
15. dgellow ◴[] No.23487371{3}[source]
What about authentication, authorization?

Also, how do you handle transactional logic?

replies(2): >>23487451 #>>23487608 #
16. osrec ◴[] No.23487403[source]
I couldn't agree more. While GraphQL does allow you to be explicit about what you want from your backend, I've yet to see an implementation/solution that gives you back your data efficiently. If anything, the boilerplate actually seems to introduce inefficiency, with some especially inefficient joins.

And when you are explicit about how you want to implement joins etc, you pretty much have to hand code the join anyway, so I don't see the point.

In almost all use cases that I've come across, a standard HTTP endpoint with properly selected parameters works just as well as a GraphQL endpoint, without the overhead of parsing/dealing with GraphQL.

17. rhlsthrm ◴[] No.23487451{4}[source]
They have great recipes for authentication/authorization. It's much better IMO because it actually provides per-request authorization. There is also great support for transactions using the GraphQL mutations. I'm not affiliated with Hasura in any way, it's just changed the way I view backend development. Backends (in most cases, my day job is actually not part of this generalization) should basically be a thin wrapper around your database, and any work you can outsource to the database, you should do that rather than building business logic.
18. devit ◴[] No.23487603[source]
The advantage of GraphQL is that the code for each API endpoint, which depends on frontend design (e.g. how many comments should be visible by default on a collapsed Facebook story), is now part of the frontend codebase (as a GraphQL query, that is then automatically extracted and moved to the backend), and thus frontend and backend development are no longer entangled.

Without it or a similar system frontend developers have to ask backend developers to create or modify an API endpoint every time the website is redesigned.

Also, it allows to combine data fetching for components and subcomponents automatically without having to do that manually in backend code, and automatically supports fine-grained caching of items.

replies(1): >>23487853 #
19. eatonphil ◴[] No.23487608{4}[source]
Those aren't hard to do if you declare up front what schema you need to conform to.

I'm working on a REST code generator (generates a Go backend and a typescript/react frontend) that reads your postgres/MySQL schema and some additional metadata you provide (should auth be enabled? Which table is the users table and which columns are username and password stored as bcrypt). I'm still working on authorization part but basically optional per-endpoint logic DSL for simple stuff and optional Go hooks for more complex stuff.

https://eatonphil.github.io/dbcore/

20. ◴[] No.23487611[source]
21. dmitriid ◴[] No.23487619{3}[source]
We're exploring a GraphQL serv(er/ice) for an internal back office system. It needs to combine multiple APIs into a single GraphQL interface. And everything just breaks apart :) (we have PoCs in C# and Java for now).
replies(1): >>23488835 #
22. eveningcoffee ◴[] No.23487709[source]
It is attractive for a front end dev who does not have control over the backend endpoints i.e. public API like Facebook.

It clearly looks questionable adaption for a single organization.

23. eveningcoffee ◴[] No.23487728{3}[source]
It is not really a backend when it does not involve business logic but just an access layer for the DB. It is pretty much a client server model.
replies(1): >>23488892 #
24. GordonS ◴[] No.23487839{4}[source]
> it reduces round trips

Is that really a big deal with HTTP2 and pipelining?

I can also imagine situations where it results in a better UX to make multiple small calls, rather than one big one, as you'll have something to render faster.

replies(2): >>23488212 #>>23488218 #
25. macca321 ◴[] No.23487853[source]
Or the frontend devs could have just, like, learned how to write sql queries... :D

A major issue with pushing it to the frontend is that malicious clients can issue unexpected requests, putting strain on the database.

If the graphql query implementation doesn't allow that level of querying on the database, then it's not offering much more before you need to speak to the backend devs than a filterable rest endpoint.

This all came up years ago with OData.

replies(1): >>23488238 #
26. GordonS ◴[] No.23487895[source]
> - good for frontend

I'm not even sure about this part.

I worked on a project recently where the mobile front end team hated working with GraphQL. They were far more used to working with REST/HTTP APIs, and in this particular project they only communicated with a single backend.

The team saw it as extra layers of complexity for no benefit.

The GraphQL backend was responsible for pulling together data from several upstream systems and providing it to clients. But the architect never was able to convince me of a single benefit here compared to REST.

27. lukevp ◴[] No.23488212{5}[source]
If you are round tripping because of data, you’re having to traverse the network to the origin and likely composing your queries with dependent data, so http2 is little benefit. For example, if you are loading a book detail page, and want to also show the author name, but you need to retrieve the detail record to get the author ID first so you can call the author detail endpoint. Graphql solves for this by being able to fetch the book detail and the joined author name with one round trip.
replies(1): >>23488293 #
28. Nextgrid ◴[] No.23488218{5}[source]
I always find it sad when developers waste time on developing over-engineered methods to reduce the amount of API calls while having 10 advertising/analytics SDKs in the background sending countless amounts of requests (which can still saturate the data link and make the main API requests stall even if it's a single one).
29. Nextgrid ◴[] No.23488238{3}[source]
My worry with GraphQL is that the server component is essentially a black box (as I don't have time to audit/review it) complex enough that there's more chance an edge case in a GraphQL query will end up exposing something you don't want.

A REST endpoint on the other hand is fairly simple and understood; there's (mostly) a static set SQL queries behind it and as long as those are not returning any unwanted data you are pretty much guaranteed to not expose something you didn't want to.

replies(1): >>23489888 #
30. GordonS ◴[] No.23488293{6}[source]
Sure, I didn't mean multiple requests would always be a net benefit, only that I often come across cases where there is a need to load independent data simultaneously, in which case multiple requests can sometimes provide a better UX.

> Graphql solves for this by being able to fetch the book detail and the joined author name with one round trip

I don't see why we need GraphQL to solve this though - a REST backend could have an endpoint that returns the exact same data.

I can see how GraphQL might be somewhat nice for front end developers when the data to be displayed hasn't been nailed down yet - maybe we decide to show the book's ISBN number, and we can do that without changing the backend. Maybe this justifies the extra complexity for some teams, but I'd personally much prefer the simplicity of a REST API, to which you can always add OData on top if you really want.

replies(1): >>23489813 #
31. DrFell ◴[] No.23488354[source]
GraphQL is instant API to frontenders.

Their justification for needing it is that the API team takes too long to implement changes, and endpoints never give them the data shape they need.

The silent reason is that server-side code, databases, and security are a big scary unknown they are too lazy to learn.

A big project cannot afford to ask for high standards from frontenders. You need a hoard of cheap labor to crank out semi-disposable UIs.

replies(2): >>23488496 #>>23491001 #
32. hurricaneSlider ◴[] No.23488435[source]
> usable only for internal projects where you have full control of who has access to your system, and can't bring it down because you forgot an authorization on a field somewhere or a protection against unlimited nested queries.

As someone who is building a public facing GraphQL API, I would disagree with this. Directives make it easy to add policies to types and fields in the schema itself, making it amenable to easy review.

A restful API also has the problem that if you want fine grained auth, you'll need to remember to add the policy to each controller or endpoint, so not that different.

The typed nature of GraphQL offers a way of extending and enriching behavior of your API in a very neat, cross cutting way.

For example we recently built a filtering system that introspected over collection types at startup to generate filter input types. We then built middleware that converted filter inputs into query plans for evaluation.

I previously worked at another company that offers a public REST API for public transport. Public transport info is quite a rich interconnected data set. Despite efforts to ensure that filtering was fairly generic, there was a lot of adhoc code that needed to be written to handle filtering. The code grew exponentially more complex as more filters were added. Maybe this system could have been architected in a better way, but the nature of REST doesn't make that exactly easy to do.

Bottom line is that I feel for public APIs, that there is a lot of demand for flexibility, and eventually a public facing RESTful API will grow to match or even exceed that of a GraphQL API in complexity.

replies(1): >>23490863 #
33. yuchi ◴[] No.23488496[source]
There’s also a different side of the story: UI are very pricey to get right — that’s because user research is not cheap — so a very efficient approach is having disposable UIs since you know you are going to get them wrong at the start.

Carefully designed endpoints require a lot of back and forth between teams with very different skill set so to build them you need to plan in advice, but it does not work here where you literally have to move fast (and fail fast!).

You only have two options left: (1) you either ask frontenders (or UX-wise devs) to do the whole thing or (2) you build an abstraction layer that let frontenders query arbitrarily complex data structures with near-perfect performances (YMMV).

In case (1) you’re looking for REAL full-stacks, and it’s not that easy to find such talented developers. In case (2) well… that’s GraphQL.

34. gavinray ◴[] No.23488835{4}[source]
You can use Remote Schemas in Hasura to combine multiple API's, and Remote Joins to join relational data across data sources:

https://hasura.io/docs/1.0/graphql/manual/remote-schemas/ind...

https://hasura.io/blog/remote-joins-a-graphql-api-to-join-da...

If you need to convert your API's into a GraphQL first, you can wrap the endpoints with resolvers yourself, or use automated tooling:

https://github.com/Urigo/graphql-mesh

https://github.com/IBM/openapi-to-graphql

replies(1): >>23496579 #
35. karatestomp ◴[] No.23488883{3}[source]
There are automagic GraphQL layers that sort-of make sense to me, since at least they remove the biggest pain points. But AFAIK they're all single-database.

Actually stitching together multiple services or DBs with it manually seems like it'd be a hellish experience that'd end in a massive data breech or repeated accidental dataloss + restore-from-backup. Or else valid GraphQL going to such a system would be so restricted that the benefit over just using REST (or whatever) is zero.

36. xgenecloud ◴[] No.23488892{4}[source]
hey, you might want to check xgenecloud where it is seamless to add business logic for generated APIs.

XgeneCloud makes it really simple to add business logic for generated APIs (REST and GraphQL both) over any SQL databases.

We just launched this week [2]

[1] : https://github.com/xgenecloud/xgenecloud

[2] : https://news.ycombinator.com/item?id=23466782

Website : https://xgenecloud.com

(disclaimer: founder here)

37. cnorthwood ◴[] No.23488907[source]
I don't see GraphQL as an ORM type solution, I see it more like a replacement for REST.
replies(1): >>23489005 #
38. AsyncAwait ◴[] No.23489005[source]
What would be the advantage of GraphQL over gRPC in a REST replacement scenario?
replies(1): >>23490132 #
39. goto11 ◴[] No.23489619[source]
I don't see the conflict? If the GraphQL query is translated into SQL on the server, then then the query optimizer would optimize that just as effectively as if the query had been written in SQL originally.
replies(2): >>23489782 #>>23490791 #
40. mixedCase ◴[] No.23489782[source]
> then the query optimizer would optimize that just as effectively as if the query had been written in SQL originally

...and other lies we tell ourselves to sleep soundly at night.

But just like ORMs, they do work for the simple cases which tend to abound and you can hand-optimize the rest.

replies(1): >>23497243 #
41. virtue3 ◴[] No.23489813{7}[source]
The real benefit of this, is that you can have all this data available, and now the mobile team and the web team can share a query, maybe the webteam wants everything, ithe ISBN the Author, etc. The mobile team only wants the author and title (and will show the rest when you click in, doing the same query or slightly different but with all the fields).

It's the power of the frontend teams to create a rest endpoint out of a schema.

When you combine it with typescript/JVM/Swift, you get AUTO typing for the graphql queries, you know exactly the data model you get back based on your query. It's quite lovely.

The other aspect is that on the apollo/graphql server you can utilize dataloader and streamline a nested request into as few calls to each service as possible.

And the last benefit over a rest service. If you had to make multiple calls, you're doing round trips from the CLIENT to the backend services. The graphql server is _already_ in your backend service network, so all the data combining is on the orders of <10ms versus <100ms (or much worse for mobile).

GraphQL has a major advantage over rest in that you can't just change the schema without the clients breaking, so you know that your API isn't going to magically just screw you. (Most places use versioning for this, but not always). You can get some of this with RPCs but it's not as robust as the graphql schema.

42. virtue3 ◴[] No.23489888{4}[source]
the graphql server has a contract (the schema) that it will follow, or 500. So you know what you get back is exactly to spec. Or you get nothing.

REST endpoints are usually way more blackbox.

You can't claim that REST is better cuz you can look at the server... when you could do the same thing to the graphql server.

Graphql will -never- return you unwanted data. Because you wrote in the query exactly what you want.

If you want to examine an endpoint and JUST what it returns, you can do so really easily with graphiql.

https://developer.github.com/v4/explorer/

Just enter the api and you get an auto complete list of all the data fields you have access to. Or just use the schema explorer and click through. 100x easier than going through a sql query and analyzing a table.

replies(1): >>23490807 #
43. chrisfosterelli ◴[] No.23489981{3}[source]
I think lots of people here are fixed on GraphQL from a backend perspective and are missing that GraphQL has a fantastic front end development experience using libraries like Apollo.

I honestly think the backend benefits are relatively marginal, but on the client being able to 1) mock your entire backend before it even exists, 2) have built in automatic caching on every query and entity for free, 3) use a fully declarative, easily testable and mockable React hook API built with out-of-the-box exposed support for loading and error states, is so valuable. Components written against Apollo feel so clean and simple. That's not to say anything about the benefits you get from being able to introspect the entire backend API or test queries against it with Apollo's extensions or how you can easily retain the entire entity cache across reloads with simple plugins to Apollo.

Can you do all that with REST? Sure. But writing queries against REST APIs is a pain in the butt compared to what you get for free by using Apollo.

replies(1): >>23491321 #
44. umvi ◴[] No.23489986[source]
Super useful for bandwidth sensitive situations where you need to piece together a small amount of data from several APIs that normally return a large amount of data.
replies(1): >>23490309 #
45. jakevoytko ◴[] No.23490132{3}[source]
I'm only passingly familiar with gRPC, so forgive me if it offers some kind of linking like what I describe below.

In REST (and seemingly in gRPC), you define these siloed endpoints to return different types of data. If we're imagining a Twitter REST API, you might imagine Tweet and User endpoints. In the beginning it's simple - the Tweet endpoint returns the message, the user ID, and some metadata. You can query the User

Then Twitter continues to develop. Tweets get media attachments. They get retweets. They get accessibility captions. The Tweet endpoint expands. The amount of information required to display a User correctly expands. Do you inline it in the Tweet? Do you always require a separate request to the User, which is also growing?

As the service grows, you have this tension between reusability and concision. Most clients need only some of the data, but they all need different data. If my understanding of gRPC is correct, it would have this similar kind of tension: business objects that gain responsibilities will likely gain overhead with every new object that is added, since the clients have no way of signaling which ones they need or don't need.

In GraphQL, you define your object model separately from how it's queried. So you can define all of these things as separate business objects: a Tweet has a User, Users have Tweets, Tweets can link to Media which has accessibility caption fields, etc. Starting from any entry point to the graph, you can query the full transitive closure of the graph that you can reach from that entry point, but you don't pay for the full thing.

This relaxes the tension between reusability and concision. Each querier can request just the data that it needs, and assuming the backend supports caching and batching when appropriate, it can have some assurances that the backend implementation is only paying for what you use.

replies(1): >>23490677 #
46. staticassertion ◴[] No.23490291{3}[source]
It's not nearly as complex as paging, which has a similar purpose of limiting single-query complexity.
replies(1): >>23492275 #
47. kodablah ◴[] No.23490309[source]
Pardon my naivete, are the benefits of the flexibility that GraphQL give worth the unpredictability costs (or costs of customizing to add limits) of that same flexibility compared to writing a tailored server side call to do those calls and return the limited data instead?
replies(2): >>23490370 #>>23490371 #
48. real_ben_michel ◴[] No.23490334[source]
Having seen many product teams implement graphQL, concerns were never around performances, and more around speed of development.

A typical product would require integrations with several existing APIs, and potentially some new ones. These would be aggregated (and normalised) into a single schema built on top of GraphQL. Then the team would build different client UIs and iterate on them.

By having a single queryable schema, it's very easy to build and rebuild interfaces as needed. Tools like Apollo and React are particularly well suited for this, as you can directly inject data into components. The team can also reason on the whole domain, rather than a collection of data sources (easier for trying out new things).

Of course, it would lead to performance issues, but why would you optimise something without validating it first with the user? Queries might be inefficient, but with just a bit of caching you can ensure acceptable user experience.

replies(1): >>23490882 #
49. GordonS ◴[] No.23490370{3}[source]
Yeah, I just don't get it - even if you use GraphQL, you're going to have to do server-side code to make the calls to the different backends.

Maybe it's just that the backend devs in my last project werenyevery good, but the backend GraphQL code was ridiculously complex and impossible to reason about.

replies(1): >>23493324 #
50. satvikpendem ◴[] No.23490371{3}[source]
Yes, as this is the main reason that Facebook created GraphQL, it is expensive for mobile phones to query that much data. Something else interesting is that while you begin to write the tailored server side call, and you optimize it, you will end up with something that looks like GraphQL anyway.
replies(1): >>23490389 #
51. kodablah ◴[] No.23490389{4}[source]
Server-to-server GraphQL seems much more reasonable as both sides are controlled. It's the client-to-server I have less of a justification for compared to targeted calls w/ individual, limited contracts that are quantifiable and optimizable. I have witnessed the costs of allowing highly flexible data fetching from the client once it grows large.
replies(1): >>23492153 #
52. GordonS ◴[] No.23490677{4}[source]
Thanks for posting this - I think your Twitter example is first I've ever read where I've actually been able to see any real benefit over REST.
53. jmull ◴[] No.23490791[source]
The SQL your graphql implementation’s ORM middleware generates won’t optimize as well as hand-written SQL in many cases.

A decent system will provide the hooks you need to hand optimize certain cases somehow, but There are always limitations and hoops to jump through and additional complexity to manage. The extra layers that are meant to make your life easier are getting in the way instead. (May or may not still be worth it, but the point is, it’s not a foregone conclusion.)

replies(1): >>23496969 #
54. grok22 ◴[] No.23490807{5}[source]
>> Graphql will -never- return you unwanted data. Because you wrote in the query exactly what you want.

But couldn't you intentionally or unintentionally write a query such that it returns too much data and borks the system? Un-intentionally is the worrisome aspect.

replies(1): >>23492112 #
55. GordonS ◴[] No.23490863{3}[source]
> A restful API also has the problem that if you want fine grained auth, you'll need to remember to add the policy to each controller or endpoint, so not that different.

This is dependent on the framework, just as it is with GraphQL - for example, with ASP.NET Core you can apply an auth policy as a default, or by convention.

> Despite efforts to ensure that filtering was fairly generic, there was a lot of adhoc code that needed to be written to handle filtering.

I've never seen this problem with REST backends myself, but I work with a typed language, C#. Again though, this is more of a framework thing than a REST/GraphQL paradigm thing.

replies(1): >>23492089 #
56. jayd16 ◴[] No.23490882[source]
I wonder if GraphQL would make more sense as a client side technology. The goals of dev ease seem better served by a graph the client can build (and thus span multiple remote services). Instead of transforming the backend, you simply get a better UI dev experience and the middleware handles query aggregation.

You'd want code gen to easily wrap REST services.

You could get some of the pipeline query/subquery stuff back (and lose caching) by setting up a proxy running this service or fallback to client side aggregation to span services not backed by the graph system (and maybe keep caching).

Maybe we're back to SOAP and WSDLs, though.

replies(2): >>23491107 #>>23493304 #
57. GordonS ◴[] No.23491001[source]
> Their justification for needing it is that the API team takes too long to implement changes, and endpoints never give them the data shape they need.

I've certainly seen timing issues between frontend and backed teams; actually, I don't think I've ever been on a project where that wasn't an issue!

But on my last project, which had a GraphQL backend, this was still a problem. The backend integrated with several upstream databases and REST APIs, so the backend team had to build the queries and implementations before the frontend could do anything. At least with REST they would have been able to mock out some JSON more easily.

58. jbreiding ◴[] No.23491107{3}[source]
Graphql is generally referred to as be4fe, meaning backends for frontend.

Not exactly client side, but the main consumer is the client and s2s or service to service isn't intended target.

59. zwkrt ◴[] No.23491202[source]
For a fun hack-week project I created a graphql server that would automatically create any necessary SQL tables to support a query given to it. So if you made the query

    query {
        user {
            name
            email {
                primary
                secondary
            }
            posts {
                body
                karma
            }
        }
    }
It would create an entire database schema with users, emails, and posts, and the correct indexes and fk relations to support the graphql query. It would also generate mutations for updating the entities in a relational, cascading manner, so deleting a user would also delete their email and posts.
replies(2): >>23491792 #>>23500426 #
60. austinpena ◴[] No.23491321{4}[source]
Plus typescript + auto generating queries from graphql-let is literally heaven.
61. rojobuffalo ◴[] No.23491786[source]
GraphQL was developed by Facebook to be used in conjunction with their frontend GraphQL client library called Relay. Most people opt Apollo + Redux because they were more active early on in releasing open source, and people argue it is an easier learning curve. IMO Relay is a huge win for the frontend to deal with data dependencies; and is a much better design than Apollo + Redux.

GraphQL formalizes the contract between front and back end in a very readable and maintainable way, so they can evolve in parallel and reconcile changes in a predictable, structured place (the GraphQL schema and resolvers). And it allows the frontend, with Relay, to deal with data dependencies in a very elegant and performant way.

62. carapace ◴[] No.23491792{3}[source]
That sound cool! Is it online anywhere? I'd love to look at it.
63. hurricaneSlider ◴[] No.23492089{4}[source]
The transport API I was referring to was written in .NET Core. I think .NET core is great at what it does, but runs into the same kinds of problems that GraphQL tries to address from the start once your API becomes sufficiently featured, which is likely to happen if you're offering an API as a service.

I actually think that unless your company is massive or has a lot of expertise in GraphQL already, using it for private APIs may not be the best idea, as it could be a sign of certain internal dysfunctions or communication problems within or between engineering teams.

----

An example, however of the kind of filtering I was referring to, and why I still think it would be non trivial to do, even in something like ASP.NET, is the following: https://www.gatsbyjs.org/docs/graphql-reference/#filter. This of course isn't something you get out the box in GraphQL either, but the structure of the system made this (relatively) easy to do.

Of course you could add something like OData to your REST API which would definitely be a valid alternative, but that also would have its own warts, and is subject to similar criticisms as GQL.

replies(2): >>23494138 #>>23496594 #
64. tomnipotent ◴[] No.23492112{6}[source]
There is nothing inherent in other systems that prevents this scenario, so why should GraphQL? This is a design decision orthogonal to whether it's REST, GraphQL, SOAP, or what have you.
replies(1): >>23514582 #
65. tomnipotent ◴[] No.23492153{5}[source]
> seems much more reasonable as both sides are controlled

GraphQL has been around for years and people keep making this argument, but where are all the horror stories of unbounded queries being made and systems being hobbled? The argument is beginning to sound anemic.

66. tomnipotent ◴[] No.23492161[source]
> but the downsides

What do you consider the downsides?

replies(1): >>23493569 #
67. nawgszy ◴[] No.23492176[source]
I would say that you're also completely ignoring the benefits of typing. It's fair to say JS's lack of typing is a deep flaw, and so tools like TypeScript and GraphQL (which pair magically by the way; free type generation!) are ways to lift the typing from the backend to the frontend and give frontends stories around typing and mocking APIs that greatly improve the testability of the code.
68. tomnipotent ◴[] No.23492219[source]
It all depends on whether you expect to 1) use GraphQL as an ORM replacement or 2) use GraphQL as a layer to aggregate multiple disparate services into a unified API.

Most people want #1, Graphene is a bad choice because you still have to write a lot of boilerplate code. It has the added benefit that the current process is responsible for parsing the GraphQL query and directly calling the database, vs. using something like Prisma/Hasura which (may) require a separate process which in turn calls your database (so 2 network hops).

GraphQL was never intended to be an ORM replacement, but many have steered it towards that direction. It's not a bad thing, but it's still the same level of abstraction and confusion that people have wrestled with when using traditional ORM's except now you're introducing a different query API vs. native code/fluent interfaces/SQL.

replies(1): >>23493141 #
69. tomnipotent ◴[] No.23492275{4}[source]
Anyone use MSSQL before it got ROW_NUMBER and window functions? Paging was a literal nightmare - if you wanted records 101-110, you had to fetch 1-110 and truncate the first 100 rows yourself (either in the DB via stored procedure or in your app code). I wish LIMIT/OFFSET was SQL ANSI standard.
70. tango12 ◴[] No.23493141{3}[source]
(I'm from Hasura)

While Hasura + GraphQL can be used as an ORM (especially for serverless functions!), Hasura is designed to be used directly by clients as well.

Hasura has a metadata configuration system that works on top of an existing database that allows configuring mapping, relationships and most importantly permissions that make the GraphQL feasible to be used by even frontend apps. [1]

Further, Hasura has remote joins that can "join" across Postgres, GraphQL, REST sources and secure them. [2]

[1] https://hasura.io/blog/hasura-authorization-system-through-e...

[2]: https://hasura.io/blog/remote-joins-a-graphql-api-to-join-da...

71. andrewingram ◴[] No.23493304{3}[source]
I always say that GraphQL is best thought of as frontend code that lives on a backend server. If in your current world you have front-end code that talks to multiple traditional REST endpoints, the frontend is therefore responsible for managing all the relationships between the API data in order to build a coherent object graph which the UI can interpret. GraphQL turns this object graph into a first class citizen that can be consistently queried, rather than something everyone keeps having to reinvent, and moves it closer to the source of truth (the downstream services) for performance reasons (so that each network hop can be measured in single digit milliseconds rather than tens or hundreds).

I've seen GraphQL schemas being implemented on the client, it's certainly doable, but the performance is terrible compared to doing it on a server close to the source of truth.

72. andrewingram ◴[] No.23493324{4}[source]
It's easy to write an incomprehensible GraphQL server the first time you try it, but it's by no means an innate trait of the technology. Assuming your downsteam APIs are done well, it should be possible to write a GraphQL server which is easy to reason about and has predictable performance (largely on par with what you'd get if you built the endpoints by hand).
73. jayd16 ◴[] No.23493569{3}[source]
No caching. Not enough benefit at the present to warrant throwing away all the restful tooling we currently have.
74. GordonS ◴[] No.23494138{5}[source]
> An example, however of the kind of filtering I was referring to, and why I still think it would be non trivial to do, even in something like ASP.NET, is the following: https://www.gatsbyjs.org/docs/graphql-reference/#filter. This of course isn't something you get out the box in GraphQL either, but the structure of the system made this (relatively) easy to do.

Ah, then I misunderstood; I was thinking along the lines of dotnet's authorisation filters.

Filtering might require some reflection, expressions or funcs, which aren't necessarily "everyday" things for some devs, but they shouldn't pose any real trouble for seasoned dotnet devs. If you really want a standard that works OOTB for Entity Framework (and I assume EF Core), you have the option of OData too.

75. dmitriid ◴[] No.23496579{5}[source]
I took a quick peek, it's no different than writing your own resolvers in any other implementation.
76. dmitriid ◴[] No.23496594{5}[source]
This filtering is a custom DSL that really has nothing to do with GraphQL.

You might get away with it in a GraphQL implementation because you can possibly slap it in top a centralized endpoint, but I really question its efficiency in this case.

77. goto11 ◴[] No.23496969{3}[source]
But why wont it optimize as well as hand-written SQL? How can the query optimizer even tell the difference? Surely the SQL is transformed into some kind of syntax-independent abstract query tree before it is passed to the optimizer.
replies(2): >>23498872 #>>23501609 #
78. Doxin ◴[] No.23497167[source]
Honestly graphql is a fairly small step up from REST if you squint at it hard enough. You could get pretty much 90% of the effect of graphql with a REST framework and a couple of conventions:

- Have the client specify which fields to return, and return only those fields

- Use the above to allow for expanding nested objects when needed

- Specify an API schema somehow.

All GraphQL does is formalize these things into a specification. In my experience the conditional field inclusion is one of the most powerful features. I can simply create a query which contains all of the fields without paying for a performance penalty unless the client actually fetches all those fields simultaneously.

GraphQL queries tend to map rather neatly on ORM queries. Of course you run into the same sort of nonsense you get with ORMS, such as the n+1 one problem and whatnot. The same sort of tools for fixing those issues are available since your graphql query is just going to call the ORM in any case, with one large addition. Introspecting graphql queries is much easier than ORM or SQL queries. I can avoid n+1 problems by seeing if the query is going to look up a nested object and prefetch it. With an ORM I've yet to see one which allows you to do that.

Lastly GraphQL allows you to break up your API very smartly. Just because some object is nested in another doesn't mean they are nested in source code. One object type simply refers to another object type. If an object has some nested objects that needs query optimizing you can stick that optimization in a single place and stop worrying about it. All the objects referring to it will benefit from the optimization without knowing about it.

GraphQL combines all of the above rather smartly by having your entire API declared as (more or less) a single object. That only works because queries only run if you actually ask for the relevant fields to be returned. It's very elegant if you ask me!

Long story short: yes you run into the same sort of issues optimization wise you get with an ORM, but importantly they don't stack on top the problems your ORM is causing already.

79. goto11 ◴[] No.23497243{3}[source]
> ...and other lies we tell ourselves to sleep soundly at night.

So tell me how the query optimizer could possibly tell the difference between generated and hand-written SQL?

replies(1): >>23498757 #
80. mixedCase ◴[] No.23498757{4}[source]
Because the SQL will not be the same. In complex cases, SQL generated by an ORM will do a combination of "more than it needs to" and plain inefficient queries. It can only do so much with what it knows about the database and the API used to call it.

Hand-written SQL gives the author a chance to be more precise in its needs, not only in the SQL but also by pre-generating obvious indexes to be performant from the get-go.

replies(1): >>23499267 #
81. mixedCase ◴[] No.23498872{4}[source]
No such thing. The database interface is SQL. The query optimizer is something run in the database.
replies(1): >>23499077 #
82. goto11 ◴[] No.23499077{5}[source]
Yes I mean inside the database engine. The engine receives SQL and parses it and then pass the query tree to the optimizer which generate a query plan. My question is how the optimizer could have problems if the SQL is generated as opposed to hand-written? How could that make a difference?
replies(1): >>23502636 #
83. goto11 ◴[] No.23499267{5}[source]
Appropriate indexes will be utilized (by the query planner) whether the SQL is hand-generated or generated from some other query languages. It doesn't make a difference. How could it?

And the whole point of GraphQL is that you specify exactly what data you need, so overfetching is avoided. This is in contrast to traditional REST API's where you get a fixed resource.

replies(1): >>23502600 #
84. ahhsum ◴[] No.23500426{3}[source]
Yo, this is legit what hasura does!
85. jblwps ◴[] No.23500683[source]
Graphiti always seemed like a cool project in this vein.

https://www.graphiti.dev/guides/

86. jmull ◴[] No.23501609{4}[source]
There are a lot of ways to write a SQL query against a set of tables, given a set of input parameters, to get the desired result. (Not just syntactic or other superficial differences, but differences in logic and how relationships are specified.)

And, of course, an optimizer will handle different SQL queries differently.

87. mixedCase ◴[] No.23502600{6}[source]
> Appropriate indexes will be utilized

If present. And for that they need to be created, and which are the right ones is less obvious when working higher in the abstraction staircase.

> It doesn't make a difference. How could it?

Because the SQL generated by ORMs can be wildly stupid in many cases. Here's one blogpost with an example, where regular SQL and query builder that maps to SQL almost directly generate a decent query on a simple relation, while a full ORM does something stupid: https://blog.logrocket.com/why-you-should-avoid-orms-with-ex...

replies(1): >>23511944 #
88. mixedCase ◴[] No.23502636{6}[source]
As mentioned in another the comment, because SQL that is hand-written for non-trivial cases will too often be better than what an ORM generates.
replies(1): >>23511081 #
89. goto11 ◴[] No.23511081{7}[source]
This is so hand-wavy I can't really argue against it.
90. goto11 ◴[] No.23511944{7}[source]
The article shows one query generator which generates SQL which are logically equivalent to the hand written SQL, and compares it to another tool which generate inefficient queries. So it is not an inherent problem with generated SQL, just with some particular tool. So...use the right tool?

GraphQL allows you to specify what data you need. Obviously, if you use some middleware which throws this information away and just fetches everything from the database, then you have an inefficient system. But this is not a problem inherent to GraphQL or generated SQL in general.

91. grok22 ◴[] No.23514582{7}[source]
With REST, for example, you usually have a smaller set of well defined APIs whose surface area is pretty visible and it could be custom optimized up-front or even disallow certain kinds of queries. GraphQL seems to provide enormous flexibility for the front-end engineer to generate any kind of request that it might not be possible upfront to anticipate all the kinds of requests that will be made and optimize them?

While it might be orthogonal to the design decision, it might add to the amount of unanticipated work that will be required just because of the enormous flexibility.

replies(1): >>23531997 #
92. tomnipotent ◴[] No.23531997{8}[source]
Nothing you said can't also be applied to GraphQL. It takes the same level of work to add pagination to a REST as it does to GraphQL, and you can add any arbitrary constraint you want as you see fit - nothing about GraphQL takes this away from you.