11 ms·
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 exactl
by WhatIsDukkha 6y ago
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 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.
- searchableguy 6y agoThat 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.
- kabes 6y ago"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.
- deleted 6y ago[deleted]
- staticassertion 6y agoIt's not nearly as complex as paging, which has a similar purpose of limiting single-query complexity.
- tomnipotent 6y agoAnyone 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.
- kevan 6y agoSeems 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.
- WhatIsDukkha 6y agoYeah 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).
- kabes 6y agoThat's indeed one of its selling points. But most products I see that adopt graphql are exactly 1 database.
- square_usual 6y agoAs 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.
- GordonS 6y ago> 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.
- baddox 6y agoGraphQL 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.
- snorremd 6y agoHasura 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-graphql-to-sql-server-58d9944b8a87/ 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.
- zwkrt 6y agoFor 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.
- PostThisTooFast 6y agoYeah, I thought it was going to be a breakthrough, which would relieve developers from the coding effort to keep the server-side and client-side query serialization in sync. But no. Last I checked, it couldn't even express joins. So how is that useful?
- dmitriid 6y ago> 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.
- rhlsthrm 6y agoAs 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.
- dgellow 6y agoWhat about authentication, authorization? Also, how do you handle transactional logic?
- rhlsthrm 6y agoThey 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.
- stevenjohns 6y agoWhere 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.
- tomnipotent 6y agoIt 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.
- tango12 6y ago(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-examples/ https://hasura.io/blog/hasura-authorization-system-through-e... [2]: https://hasura.io/blog/remote-joins-a-graphql-api-to-join-database-and-other-data-sources/ https://hasura.io/blog/remote-joins-a-graphql-api-to-join-da...
- jayd16 6y agoI 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.
- tomnipotent 6y ago> but the downsides What do you consider the downsides?
- jayd16 6y agoNo caching. Not enough benefit at the present to warrant throwing away all the restful tooling we currently have.
- jblwps 6y agoGraphiti always seemed like a cool project in this vein. https://www.graphiti.dev/guides/ https://www.graphiti.dev/guides/
- osrec 6y agoI 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.
- devit 6y agoThe 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.
- macca321 6y agoOr 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.
- Nextgrid 6y agoMy 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.
- virtue3 6y agothe 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/ 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.
- deleted 6y ago[deleted]
- eveningcoffee 6y agoIt 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.
- DrFell 6y agoGraphQL 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.
- yuchi 6y agoThere’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.
- GordonS 6y ago> 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.
- cnorthwood 6y agoI don't see GraphQL as an ORM type solution, I see it more like a replacement for REST.
- AsyncAwait 6y agoWhat would be the advantage of GraphQL over gRPC in a REST replacement scenario?
- jakevoytko 6y agoI'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.
- 6y ago
- goto11 6y agoI 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.
- mixedCase 6y ago> 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.
- goto11 6y ago> ...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?
- mixedCase 6y agoBecause 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.
- goto11 6y agoAppropriate 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.
- umvi 6y agoSuper 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.
- kodablah 6y agoPardon 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?
- GordonS 6y agoYeah, 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.
- andrewingram 6y agoIt'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).
- satvikpendem 6y agoYes, 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.
- kodablah 6y ago
- real_ben_michel 6y agoHaving 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.
- jayd16 6y agoI 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.
- jbreiding 6y agoGraphql 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.
- andrewingram 6y agoI 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.
- rojobuffalo 6y agoGraphQL 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.
- nawgszy 6y agoI 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.
- Doxin 6y agoHonestly 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.