8 ms·
I bought into the hype and I feel bad for the company where I implemented it. One true endpoint to rule them all and cause endless headaches in the process. Wi
by joshstrange 2y ago
I bought into the hype and I feel bad for the company where I implemented it. One true endpoint to rule them all and cause endless headaches in the process.
With most tech that I screw up I assume that "I wasn't using it right" but with GraphQL I'm not sure how anyone could. The permissions/auth aspect alone is a nightmare. Couple that with potential performance issues (N+1 or just massive amounts of data) and I want nothing to do with GraphQL anymore. Everything we attempted to fix our permissions issues just caused more problems. It would break existing queries and debugging GraphQL sucked so much.
If you only live on the frontend and someone else is responsible for the backend GraphQL then I understand why you might like it. From that perspective it's amazing, you can get as little or as much as you want with the specific fields you want. No waiting on the backend team to write an endpoint. However even then you end up saving queries as files or abstracting them (maybe IDE support has improved but it wasn't great last time I was using it ~5 years ago) and now you just have REST endpoints by another name.
At one point we considered whitelisting specific queries and that's when I knew we had gone too far and made a mess for ourselves. If we had taken the time to just write REST endpoints instead we would have gotten way more done and had way fewer grey hairs.
- hosh 2y agoHmm. I wonder if there is some kind of query builder that can live server-side. That is, capture the flexibility of a query language when developing, and then consolidating that when going into production. Though I guess you can do that with REST too. I'm currently exploring all of this myself. I have a side project in mind that can use a graph db, and I thought a front-end graphql can work well with a graphdb backend. I was not sure why this pattern is not more popular, but reading all of this now, I'm seeing where these problems may arise. A graph db backend can use efficient graph search algorithms, especially for deeply nested data, but the issue with authorization is still there. If anything, fine-grained authorization is something better represented with graph dbs than with relational databases.
- groone 2y agoEntity Framework Core has got you covered! Writing some LINQ and returning data in Aspnet Core API takes no time at all.
- janmatejka 2y ago> Hmm. I wonder if there is some kind of query builder that can live server-side. That is, capture the flexibility of a query language when developing, and then consolidating that when going into production. Like a stored function in postgresql? https://www.postgresql.org/docs/current/xfunc-sql.html https://www.postgresql.org/docs/current/xfunc-sql.html
- nkozyra 2y ago> Hmm. I wonder if there is some kind of query builder that can live server-side. That is, capture the flexibility of a query language when developing, and then consolidating that when going into production. I think this is what a lot of people end up doing (and yes, with REST). Translating options via query params / POST body into a query. In theory GraphQL was supposed to mitigate this DSL-like translation, but the thing is people like flexibility and ability to change and, yes, break backwards compatibility. That's also why a lot of people end up with a translation layer with things like RPC, which is itself supposed to be a direct, shared communication protocol. The messiness of APIs is often a feature, at least internally. These approaches that attempt to avoid the mess are better for the end consumer but cause friction within development groups and the benefits are often obscured.
- AaronFriel 2y agoThis is a vague recollection, but I seem to recall Meta/Facebook engineers on HN having said they have a tool that allows engineers to author SQL or ORM-like queries on the frontend and close to where the data is used, but a compiler or post-processor turns that into an endpoint. The bundled frontend code is never given an open-ended SQL or GraphQL interface. And perhaps not coincidentally, React introduced "server actions" as a mechanism that is very similar to that. Engineers can author what looks, ostensibly, like frontend code, merely splitting the "client" side and "server" side into separate annotated functions, and the React bundler splits those into client code, a server API handler, and transforms the client function call into the annotated server function into an HTTP API call. Having used it for a bit it's really nice, and it doesn't result in yielding so much control to a very complex technology stack (GraphQL batchers, resolvers, etc. etc.)
- svieira 2y ago> I seem to recall Meta/Facebook engineers on HN having said they have a tool that allows engineers to author SQL or ORM-like queries on the frontend and close to where the data is used, but a compiler or post-processor turns that into an endpoint. I don't know about on-HackerNews but there's a discussion about their "all of Facebook optimizing compiler" infrastructure from when they did the site redesign in 2020: https://engineering.fb.com/2020/05/08/web/facebook-redesign/#:~:text=Delivering%20data%2Ddriven%20dependencies https://engineering.fb.com/2020/05/08/web/facebook-redesign/... > perhaps not coincidentally, React introduced "server actions" as a mechanism that is very similar to [the above] Yep - there's also the Scala framework LiftWeb (https://www.liftweb.net/ https://www.liftweb.net/), the Elixir framework Phoenix (https://www.phoenixframework.org/ https://www.phoenixframework.org/) and of course the system we're using right now (Arc) that do similar things. Scaling these kinds of UUID-addressed-closures is harder (because the client sessions have to be sticky unless you can serialize closures and send them across the network between servers).
- jamra 2y agoCode generation is very common at Meta. One just needs to create a query or fragment. A fragment can be spread at the root query level using relay so it will do the fetch once. It gets more complex because you can lazily query more data based on parameters you pass into GQL. It feels like magic and is really annoying imo.
- andreimackenzie 2y agoAssuming the query language for the graph DB you have in mind is declarative like SQL, I recommend templated queries. I have found this technique scales pretty well for query complexity, makes it relatively trivial to "get to the query" if something needs to be debugged in the details more easily outside of the app, and it makes performance-oriented optimization work far easier. I've had my share of headaches with the various flavors of ORM and GraphQL and always come back to query templates, e.g. MyBatis in the JVM ecosystem or Go's template package. There is still value in abstracting this from the REST web service interface to make it possible to change the app<->database connection without disrupting REST clients. It's possible to reuse parameter structs/classes between the REST client and DB+template client layers to avoid a lot of rote translation. It seems simple and repetitive, but actually saves time compared to the GraphQL/ORM complexity as apps & query complexity scale, in my experience.
- Onawa 2y agoEdgeDB? Graph database built on top of Postgres so you can do row-based auth as well. https://www.edgedb.com/blog/edgedb-5-introducing-passwordless-auth https://www.edgedb.com/blog/edgedb-5-introducing-passwordles...
- hosh 2y agoI am looking at Apache AGE because it is a Postgres extension and it parses openCypher
- bpicolo 2y agoBack when GraphQL started being around, I prototyped a proxy server that accepted a JSON dsl to resolve a series of calls to a backend JSON/REST API, so that the chain of calls would be batched up closer to the server. Worked pretty well. Definitely something that could be make to. Kind of graphql themed but how it translates to REST can be explicit.
- burutthrow1234 2y agoGraphQL absolutely feels like a technological solution to an organizational problem. What if your front-end team wants to write crazy queries and your back-end team wants to build their resume doing Real Engineering, but what you actually need is just a CRUD app? Now your backend devs aren't bored writing "business logic" and your front end devs aren't bored waiting for your backend devs. You have a new class of inscrutable errors and performance issues, but that's why you pay your backend devs the big bucks! Because some guys from a technical college couldn't possibly solve your issue, you need to pay 250k to people who went to Stanford or Berkeley.
- torginus 2y agoThis. The past few years I've been a 'full-stack' engineer - which is code for a backend guy who knows frontend. In my personal taxonomy, a frontend developer is someone who cares a lot about UX, and making things look pretty, who also writes code. I've met a lot of these people and they were more than happy to hand over all the infrastructure plumbing side of frontend apps to me - which I did along whatever REST API needed implementing on the server.
- jack_riminton 2y agoYep, Conway’s Law: “ Any organization that designs a system will inevitably produce a design that mirrors the organization's communication structure. “ Your point about Resumé Driven Development, together with the dividing wall between front and backends is why FE frameworks have got so hideously and needlessly complex imo
- belter 2y agoIn other words...Once in a while a new generation of software developers champions frameworks that not only repeat historical mistakes, but also systematically dismiss the proven wisdom of older developers. Must be that experience ages out like old code...
- ForHackernews 2y agoSounds good to me. I'll do GraphQL for $250k.
- giantg2 2y agoMy biggest problem is that it seems like nobody understands the data or where the data is coming from. You can have the same variable names and mostly even the same values under different levels of the graph. Now someone has to figure out what system is feeding that info to GraphQl to figure out which level we should use. I don't see this as a real GraphQl problem, but more so a problem with the process discouraging detailed knowledge and documentation.
- fennecfoxy 2y agoYou can write shit in any framework or language though. That's why I always found Typescript such a boon; it provides a way to box people in to use code/framework how it was designed to be used.
- giantg2 2y agoIt's definitely possible to write shit in anything. It just seems that writing something more structured, like SQL stored procs and a REST endpoint, means someone had to actually think about what data is coming back, it's structure, and how it's being used and the dev generally had better insight as to where the data was coming from and what values to expect. There's a lot about graphql that is really cool. It just seems like the way my company uses it is to cut corners.
- fennecfoxy 2y agoThe same structure thinking etc can and should be done for GQL as well. But same same, once you have project handoff some other team can pick up your nice rest api and not follow existing conventions at all. I've seen far too many rest apis that will do all these variations across the one API: delete /user/comment, post /user/comment?action=delete, post /deleteUserComment, etc. I'd agree that GQL is definitely one of those "gets used because it was the cool thing at the time" technologies but I still think it has a place in our toolboxes, it's definitely not the right solution for every problem.
- lcnmrn 2y agoSomeone like you made me quit my first job as developer. He implemented a Clojure + GraphQL nightmare.
- joshstrange 2y agoWell that wasn't me, I implemented an Akka + GraphQL nightmare instead :) Joking aside, I'm sorry that happened to you and I'm sorry for the people that took over the system I helped to write.
- mlnj 2y agoBeen there, done that. Did Akka; thank goodness that didn't make it to production. GraphQL: Helped in many ways. Hurt in so many too. In production. Everything in Actors: State was everywhere. So much pain. In production. I just use Postgres + RPCs for everything now.
- joshstrange 2y agoYeah, I love my TypeScript serverless backend project and my successful DynamoDB project but often I think I could have saved a lot of pain by using PHP and/or Postgres.
- subsaharancoder 2y agoDid the person use Lacinia? https://lacinia.readthedocs.io/en/latest/index.html https://lacinia.readthedocs.io/en/latest/index.html
- nfw2 2y agoWhitelisting the queries that clients can use in prod actually doesn't seem like a bad option to avoid a lot of these security issues, assuming you control the clients
- deleted 2y ago[deleted]
- joegibbs 2y agoYeah but then you’ve basically just remade REST, but the queries are stored in the frontend instead.
- shados 2y agoNot really. The usual strategy for persisted query is to only use them in production or adjacent areas. You build your app using regular graphql doing whatever you need, then after you tested things and it all looks good, when you ship, you parse the codebase, store the queries, and ship them. It doesn't work if you don't have control over the client (eg: exposing to third parties), in which case query complexity limits are easy to implement and do the job, too.
- wasyl 2y agoI don't understand this argument, how is it "remade REST" if you still don't need to implement and maintain an endpoint with exactly the data that clients need? Persisted/whitelisted queries require much less backend effort, and are decidedly different from REST, the only similarity is in having a closed set of possible actions. Perhaps you're thinking in terms of public APIs where I agree limiting available GraphQL queries makes little sense. But for internal APIs, whitelisting whatever queries current clients need isn't any less convenient
- joegibbs 2y agoI might be thinking about this the wrong way, but with GraphQL you're writing a query (in the GraphQL syntax) on the frontend which gets whatever data the frontend needs for whatever it's doing, and that query is interpreted by the backend to fetch specific data. But if you're whitelisting specific queries, which has to be done on the backend, what if you just move the queries themselves to the backend, and call them from the frontend by specific names for shorthand? And then from there, what if you refactored it so that each "query" was just a function with an associated endpoint?
- teaearlgraycold 2y agoI think a lot of people like GraphQL because it provides strongly typed API interfaces. But I've been able to hack together a better REST alternative in full-stack typescript codebases. And my solution doesn't need to compile any kind of client or intermediary.
- esafak 2y agoYou can type your REST API too. https://restfulapi.net/json-schema/ https://restfulapi.net/json-schema/
- rbalicki 2y agoGraphQL gives you the ability to compose fragments, so if the UserDetail component and UserPaymentInfo component both use the user’s name, it is loaded once. With ad hoc solutions like tRPC, you end up fetching the same field multiple times (and probably doing some sort of network waterfall), or you give up on data masking and composability. And if you have enough engineers, data masking and composability are critical to maintain velocity.
- teaearlgraycold 2y agoswr can handle the first issue you mentioned just fine.
- rbalicki 2y agoI'm not sure I follow. Are you saying swr allows for fragments and deduplication? If you don't have fragments (in particular, if you have a single call to an swr hook at the root), then you have implicit deduplication. But then you run into the issue of it being unclear whether you can remove a given field when a subcomponent stops using it — you have to check whether any other subcomponent happens to use that. And if you have many separate queries, you're architecting in waterfalls. But you have clarity about who uses which field.
- teaearlgraycold 2y ago
- awongh 2y agoI’ve only been a consumer of a GraphQL API, so I don’t know what it’s like to maintain, but I mostly enjoyed using it. Of course the documentation on some kinds of query syntax was too sparse, (this is for Shopify) but I could see how it might be nice for certain kinds of cases. If you run a platform it might be a good option to offer in your API. For shopify afaik there are equivalent calls in both REST and graphql so you have options.
- pas 2y agoCan you elaborate on lack of syntax docs? As far as I understand one of the big big huugge benefits of GraphQL is that you get the strongly typed schema via the introspection query, so you can build queries with some confidence, that as long as the schema (version) is the same it should be syntactically okay. What did Spotify do compared to this?
- albertgoeswoof 2y agoThis is one of the problems with graphql, there are no docs because the schema is all you need. But that assumes the schema is logical and consistent, which it rarely is. It also means you need to be an expert in the tooling to figure it out, so just dropping in to a graphql api is so frustrating compared to plain old rest
- pas 2y agothis was also the problem with WSDL and REST itself, and so on. of course there are things that make sense to be in-band .. but there are things that have to be communicated out-of-band (just as REST doesn't say anything about what to do with a specific content type OpenAPI and GraphQL doesn't worth much with empty description fields, though I'd argue still much better than getting a .doc file named API_doc-Finalv2(1) :) )
- rezonant 2y agoAlso there is no standard for exposing the schema, and sometimes there isn't a schema at all. Sometimes a vendor will have the schema downloadable from their dev docs, sometimes it will be an endpoint that serves it up, and sometimes they just don't give it to you and expect you to use GraphQL Explorer directly to discover what you can do. When I encountered this I figured surely GraphQL Explorer must be fetching the schema, but I guess this is not always the case, as I never was able to get a complete schema that worked with the tooling. For that vendor, there was no way to generate client code for the schema using one of the many GraphQL client library generator frameworks.
- healthdare 2y agoHow does an engineer buy into hype? Ur supposed to be analytical. Everytime some new frontend bs like tailwind comes out I roll my eyes. People want to be famous not practical. React is only popular because of Facebook and react native. It's a shit ecosystem and frontend tool set. Webpages are slow due to bloat not shadow dom.
- pyr0hu 2y agoCan you give an example for the permission issues that you had with GQL and would've been easier in REST? Genuinely curious, as I'm implementing a GQL backend with simple permission handling and haven't run into anything yet, but I wanna know what could await me
- joshstrange 2y agoWith REST I can fairly easily filter out any data based on roles/permissions either at query time or before turning it into JSON. With GraphQL I need that info deep in the resolver logic and for nested data I don't want to fetch the name of a person if they calling user doesn't even have access to see that user (and I don't want to fetch the user and their name only to delete it from the response later). GraphQL, being so open-ended to what you are fetching, means I have to make sure to plug a ton of holes whereas REST I have a specific query, there is no way to fetch nested data (unless I specifically allow it via GET/POST params). I can easily say "If role X -> use this query, if role Y -> use this query, etc", I found that very difficult to do in GraphQL. GraphQL feels like magic when you first start with it (which should be a red flag) but once you need to support more roles or sets of permissions and as your business logic starts to creep in things go haywire. In my experience things that are easy up front are unmanageable once business logic gets added in. For straight CRUD it's amazing but very rarely do our apps stay as just CRUD and that's when things fall down. For example, on create of a new user I need to send a welcome email. It's been 5 years since I was working on that GraphQL project but I have no clue how we'd handle that. I'm sure there is some kind of a event system we could hook into but with REST I just have a simple endpoint that saves the data to the DB and then sends and email (or puts it in a queue), way easier than in GraphQL. Again, fetching and updating data is easy until you need to handle edge cases. I have the same feelings about Firebase and friends. Feels like magic at the start but falls down quick and/or becomes way too complicated. GraphQL feels like DRY run amuck, "I have to keep writing CRUD, let me abstract that away", ok but now if you need special logic for certain use-cases you have a mess on your hands. Maybe GraphQL has ways to solve it but I'll bet my hat that it's overly complicated and hard to follow, like most of GraphQL once you get past the surface. I'd love to see a "Pet Store" (I think that's the common example I've seen demo'd in REST/Swagger/GraphQL/etc) example with heavy restrictions based on different users/roles. It's like using the "Todo app" example in a framework, sure that works and is straight forward, I want to see how you handle the hard stuff and if it's still easy.
- mattacular 2y agoI had an eerily similar experience with GraphQL where by the end of "productionizing" the backend to support the client load, were using whatever their equivalent of cached/persisted queries is called (sorry I can't recall their terms for this). We had ultimately come full circle to something that was harder to use than a REST API but also more complicated at every layer.
- hackthemack 2y agoOne of the things that really burned me out over the years is how many times I would say something to the effect of "Maybe using GraphQL is over complicating the process and we should just use the old tried and true methods" and I would get drowned out by everyone chasing the latest thing or derided for not wanting to try something new. "Maybe implementing CORBA for message passing is over complicating it." "Maybe using OOP and facade classes is over complicating it." "Maybe using XML to store all the config information is over complicating it." "Maybe using this ORM with a strange file based caching mechanism is over complicating it." And always get drowned out by everyone going with the trend.
- Yhippa 2y agoThink about all the LinkedIn clout you missed out on by not incessantly talking about the ${NEW_THING}!
- dventimi 2y ago"Maybe using a general-purpose programming language instead of just SQL is overcomplicating it," said I every day of my life for the past 25 years. Oh well. You can't fight City Hall.
- fouc 2y agoI'm always reminded of the mantra "Choose Boring Technology" https://boringtechnology.club https://boringtechnology.club
- vintermann 2y agoThere's boring and there's boring. Personally I think Java EE / beans and SOAP is really boring, but I would never, ever choose it.
- AlchemistCamp 2y agoFor a long piece that doesn’t once mention Erlang or Elixir, it’s the strongest argument for using them I’ve read. You could literally replace every part of any of the stacks he mentioned with Erlang. Python/PHP, cron, memcache, even the databases in the extreme case. It’s an older tech, too, so in his model this amounts to spending m zero innovation tokens for the entire stack.
- storafrid 2y agoHow many underlying services and clients was the GQL layer catering to? How many different digital products and independent teams? You referred to "the backend team" (one) and did not mention stitching/federation. This makes it likely that you were using GraphQL to address a set of needs that may not be aligned with the goals of GraphQL. Just like the author of the article - it sounds to me like he probably has been working in contexts where he would not have been able to see the org/collab/infra benefits of GraphQL. Much like the case with microservices. Enterprise tech/arch solve more than just technical problems.
- fennecfoxy 2y agoI dunno, I still quite like GraphQL, but as with all technologies it can be misused; a lot of the schemas I've seen are pretty poorly written, but the spec certainly doesn't make it easy with design choices like: no type inheritance, fields are optional by default (causing huge annoying problems with GQL->TS). Adding a few linting rules helps as well. The problem I always had with rest was that nobody really follows any patterns, not in the same company, not in the same project. There are a million different decisions you can make with rest and if you let a dev alone to build it themselves you're gonna get yet another variation, whereas GQL is only implemented according to a spec. The N + 1 problems are pretty much fixed these days & mostly any dev can build something in themselves to fix it if they want to. Permissions/auth is relatively easily achieved with middleware and directives, though it's also totally possible to roll your own by writing something that inspects the querys AST if you really need to have your auth layer separate to your schema.
- vidarh 2y agoLast place I built a complex REST app, I solved this by auto-generating a set of standard endpoints from the database schema, and then adding a UI where a small set of trusted users could write queries that'd be stored in a table that were then made available. It provided an escape hatch that allowed rapid prototyping, and came with a default UI, and then we cleaned up the ones that were worth it.
- julik 2y ago"What if I told you that 99% of GraphQL can be replaced with a QUERY HTTP call with an {"ids": [123, 456, ...]} in the request body?.."