Hacker News new | past | comments | ask | show | jobs | submit login
GraphQL kinda sucks
720 points by randytandy on Aug 6, 2022 | hide | past | favorite | 433 comments
Graphql is great, but is totally over hyped. This is probably more of a rant or a frustrated dev outburst.

but beginner to mid level developers are lead down the path of USE GRAPHQL especially on youtube... and this is just unfair and wrong.

The good:

- It makes working with describing the data you want easy

- It can save you bandwidth. Get what you ask for and no more

- It makes documentation for data consumers easy

- It can make subscription easier for you to use

- Can let you federate API calls

The bad

- It is actually a pain to use, depending on the backend you are using you'll have to manage

two or more type systems if there are no code first generates in your language

- It doesn't support map/tables/dictionaries. This is actually huge. I get that there might be

some pattern where you don't want to allow this but for the majority of situations working with json api's you'll end up with a {[key: string] : T} somewhere

- No clear path for Api versioning you'll end up with MyQueryV1.01 MyQueryV1.02 MyQueryV1.03

Don't use Graphql unless you're managing a solution/problem set that facebook intended graphql for

Invest your time in a simpler solution then running to GraphQL first

thanks for reading my ted talk

please any senior dev's drop your wise words so that any new dev's can avoid tarpits




The biggest problem with graphql is that you have to do a lot of non-obvious work to harden your system against DOS attacks or people that want to fly by and download your whole database. It's easy to construct a query which puts unreasonable load on your system.

The more fine-grained nature of boring REST calls makes it more easy to control client impact on the system.

If you want to see the kind of work you actually need to put in to make a graphql API, look at Shopify. They have rate limits based on quantity of data returned. Cursors and pagination. The schema is a huge ugly mess with extra layers that never show up in the pretty examples of GraphQL on the internet.

Note that even if you use graphql for a private api to your web client, folks will reverse engineer it and use it for their own purposes. There are no private apis on the web.

I'm not a fan of graphql for anything that the public could see. It's somewhat akin to exposing a SQL interface; it opens up too many avenues of trouble. Keep public communication channels as dumb as possible.


We avoid this by statically analyzing the queries that are used by the client, generating id’ed persisted queries for them, and only allowing those to be run if you’re un-authenticated/a regular user.

We also have user roles, which, if you’re an admin, you can run raw queries of whatever you want, but basic users are locked to the persisted query options.

It’s pretty cool, definitely adds complexity to our builds/permissions, but it works. We rolled our own, but I think Apollo GraphQL supports this out of the box now.

Not saying people should use GraphQL for everything though. It’s kind of overkill for a lot of apps.


> We avoid this by statically analyzing the queries that are used by the client, generating id’ed persisted queries for them, and only allowing those to be run if you’re un-authenticated/a regular user.

I worked with a team that was going down a similar path. At some point it felt like they were reinventing REST on top of GraphQL with a strict set of predefined queries and result shapes.

They hadn't gone too deep into GraphQL tooling so we just switched to REST and implemented those predefined queries. Had a separate, developer-only GraphQL endpoint for prototyping things for a while, but the production stuff was easier to just build out as plain old REST.


One of the objectives of GraphQL is to replace REST, so yes, you’re right, it’s re-inventing REST.

I’m not going to argue whether one is better than the other implementation wise. That’s purely personal preference.

GraphQL has one super power though. I have access to an API directly and can save bandwidth by only querying and returning what I explicitly want in the data. That plus the allowed query rules stuff comes free in Apollo GraphQL now. At scale, this is huge for our bandwidth cost savings.

A second big win is federation of many GraphQL schemas under one giant god schema. This is useful when you are a big company, merging two architectures with different API’s together under one umbrella. You can define the mappings from the child schemas to the god schema in another spec that has no code, just a federation schema. Again, you can do this in REST too with layered API’s, but GraphQL arguably makes it somewhat easier to do this with just config files.

I also find that out of the box, the type safety guarantees of GraphQL are a lot cleaner/batteries include than the REST work I did the many years prior.

It’s all do-able with either tech and you are correct in feeling like it’s re-inventing the wheel. It is, and that’s purely a business decision to make money pivoting devs to a new library/environment.

I won’t judge you for wanting to stick with REST. It’s tried and true methods that will work for many many use cases. To each their own!


> I have access to an API directly and can save bandwidth by only querying and returning what I explicitly want in the data.

I don't see how REST is not able to do this, not to mention that REST is very well suited for HTTP caching.


Saving bandwidth is really not the actual super power. The main advantage is being able to save network requests by fetching all required data in the same request.


> The main advantage is being able to save network requests by fetching all required data in the same request.

This is not really GraphQL's selling point.

GraphQL's only selling point is this handwaving-driven promise that dev teams no longer need backend work to get an API that returns the data they want.

The promise is that frontend teams simply put together a query and the server magically returns what they want.

Of course the people promising this magic just so happen to be the same people trying to sell you backend services.


I know I can make an API endpoint in Rails equally as fast as writing a query in GraphQL and the code needed to use it. I don't really buy into GraphQL yet since I have not come across a strong enough advantage of using it in my carrier. Although I do see the advantage of basically being able to run SQL through the browser. Unfortunately it is just one of may technologies over hyped by JavaScript developers.


Agreed - REST APIs can include a field mask or similar for sparse selection on a single entity but you'll still need several requests to fetch fields on related entities.


Yes that is the one strength I think GraphQL has that should be undeniable even though I am not a proponent of GraphQL myself.


I just wanted to hop in and agree with you. I’m still think REST APIs have their place and are easier to work with. If someone had recommended GraphQL 5 years ago I would’ve been against it but Apollo is good enough that I think it’s a fairly safe choice for teams to make.

One thing you do need to watch for is preventing clients from doing stupid things by allow listing queries or implementing some sort of query cost analysis.


We did research on solving the DOS issue using static analysis at IBM (cf. https://arxiv.org/pdf/2009.05632.pdf). Our findings were that static analysis allows to determine (relatively strict) upper bounds on query complexity, which we assessed for two production GraphQL APIs (GitHub and Yelp). However, the static analysis requires some configuration to determine the (maximum) size of lists.

I was later involved in productising said research into an API gateway (called DataPower) offered by IBM. We implemented our GraphQL static analysis in a quite flexible and performant way (all of GraphQL's query validation and the static analysis are implemented in C++). The required configuration for the static analysis can be provided using GraphQL schema directives (cf. https://ibm.github.io/graphql-specs/cost-spec.html). Unfortunately, DataPower is quite inaccessible to the common developer.

I find that persisted queries are a very interesting approach to also solve this issue. They still grant developers the full flexibility to define queries during development, but then require providers to validate and vet queries only once before persisting them (instead of validating and vetting queries on every request). This has huge benefits for runtime performance, of course.


It's also not that hard to implement attribute filtering with REST endpoints. People make a big deal about being able to control the shape of your API responses with GraphQL, but this completely achievable with standard REST APIs as well.


Sure, you could have a syntax for requesting (potentially recursive) nested resources in the query string of a REST API, and there are some systems that do something close [0], but if you do it’s probably a less friendly syntax than GraphQL and has all the same problems as GraphQL regarding performance and rate limiting.

[0]

A very simple convention for including nested resources in a JSON API: https://www.jsonapi.net/usage/reading/including-relationship...

A totally cool but kinda over the top library that exposes a REST API over your database with a very GraphQLesque query string syntax that supports recursively nested resource inclusion, filtering, etc.: https://postgrest.org/en/stable/api.html#nested-embedding


99% of the time you don't need to be recursive though. Field filtering with 1 level of expansion for related resources solves 95% of problems for you, and if you're implementing something on your own API, you can have a custom route for the 5%.

GraphQL falls into the same trap that a lot of things do IMO - it assumes that because 5% of things are complex, that you need a solution that can deal with that complexity for 100% of your API, which needlessly complicates everything else.


> Sure, you could have a syntax for requesting (potentially recursive) nested resources in the query string of a REST API

Or you could just make an endpoint that gives you the data you want.


That endpoint has to be unique for the client, otherwise someone else could abuse this API and when you filter out an attribute the rogue user depends on, you break their application.


No it doesn't. It's just a GET request with a parameter or two. People make this stuff so hard when it doesn't need to be.


Reminds me of http://odata.org/


Agree with this. We created our own nested query language using matrix params and path separators to let the client query for nested sub-resources, including filters against collections.

It’s pretty neat but nice graphql standardized it so things like consoles and other tools can be written against it.


This approach builds on the persisted queries approach: https://docs.wundergraph.com/docs/features/graphql-to-json-r...

It gives you all the benefits of GraphQL during development while in production you’re only dealing with JSON-RPC


> Note that even if you use graphql for a private api to your web client, folks will reverse engineer it and use it for their own purposes. There are no private apis on the web.

How is this a GraphQL specific problem?


At least compared to classical REST, usually access is limited to whatever the programmer explicitly chose to add, instead of being open by default.


That’s weird. You explicitly choose what to add to your GraphQL API too. If you’re just setting up a random library that exposes your entire database, that’s no fault of GraphQL.


Yeah, I caught that too. A lot of comments sounds like they're relying on Prisma/Husara/etc. to map directly to the database. I'm sure it's fine for some use cases (such as when prototyping), but I prefer to design and build out GraphQL APIs with a more UI/product-centric approach, which hide most of the database details.


I think it's a marketing problem. GraphQL can easily sound like "Give the entire schema to your users and let them decide what to query for". If you look at various GraphQL supportive websites, that is a common anthem. You don't get that marketing from REST. REST says "decide what's good for them".

Obviously you can do either in either. But i definitely think the marketing is world's apart.

So when people come to a problem, if they are not super strong in their understanding of what will be a good solution, they generally implement what the platform markets.


It's not, but the OP is saying this to pre-empt the "just use GraphQL for private APIs" defence.


We solved this by turning GraphQL into a compile time problem and replacing it with JSON-RPC as the transport, keeping GraphQL entirely hidden on the server. It's not just great for security and performance reasons, but also comes with a lot of other benefits, like you can inject claims into Operations. Here's some more info: https://docs.wundergraph.com/docs/features/graphql-to-json-r...


How could someone reverse engineer anything other than your data model from gql queries?


> It's easy to construct a query which puts unreasonable load on your system.

Can you give an example?


https://payatu.com/blog/manmeet/graphql-exploitation-part-4

query dos { allDogs(onlyFree: false, limit: 1000000) { id veterinary { id dogs { id veterinary { id dogs { id veterinary { id dogs { .....


Details will depend on your schema, but the moral equivalent of “SELECT * FROM master_table” is a good start.


Have you seen the “turn your database into a graphql schema” products? I shudder at the poor souls who used those products. I mean, I assume they are decent products, but man, it’s got to be so easy to screw it up and literally expose too much…


Hasura seems to be fine which we use internally in our company, though to be honest I don't do any complex queries and I don't think anyone is doing aggressively nested joins.


I think that can be part of the problem: if you use it for a few things which make sense, you get used to it and everyone thinks it's pretty solid after a while and probably starts using and likely exposing it in other areas. Then you get someone new writing different code or a clever attacker and it turns out there was a lot of room to expose unintended data or create performance issues.


I don't think hasura allows unbounded queries by default? I'm not 100% sure though, I didn't set it up at where I work.


It's actually worse than that, because with graphql you can create a single query which is the moral equivalent of:

SELECT * FROM master_table LEFT JOIN sub_table LEFT JOIN sub_sub_table LEFT_JOIN sub_sub_sub_table...

...which is effectively "dump everything". In a REST environment you'll at least need a lot more individual requests - that's both the blessing and curse.


That’s exactly what it is, a made up sql layer over sql exposing a special port. Ridiculous.


Having worked in big tech and small startups, I think GraphQL is a brilliant way to solve an organizational problem that massive tech companies have.

It's that the team maintaining the API is different from the team that needs changes to the API. Due to the scale of the organization the latter doesn't have the access or know-how to easily add fields to that API themselves, so they have to wait for the maintainers to add the work to their roadmap and get back to it in a few quarters. Relevant Krazam: https://www.youtube.com/watch?v=y8OnoxKotPQ

At a small start-up, if the GET /foo/:fooId/bar/ endpoint is missing a field baz you need, you can usually just add it yourself and move on.


That's the theory. In my experience at both large and small organisations is that NONE of the theory makes it into practice.

Some reasons:

- Front end devs save time by.... sharing queries. So component B ends up fetching records it has no use for because its sharing GQL with component A.

- Backenders never optimise column selection. You may think you are really optimising by sending a GQL query for one column, but the backend will go ahead and collect ALL the columns and then "filter" down the data that was asked for.

- Backenders can also forget to handle denormalisation. If you query related many to many records but the GQL only asks for related ids of implementations will go ahead and do a full join instead of just returning results from the bridge table.

- Frontenders aren't even aware you can send multiple graphql GraphL requests simultaneously.

GraphQL is great, but any technology is limited by how well people can extract its value. I personally feel sometime we'd be better off with REST, or at least make sure people receive the training to use GraphQL effectively.


> Front end devs save time by.... sharing queries. So component B ends up fetching records it has no use for because its sharing GQL with component A

An unfortunate problem that really only exists with Apollo. Facebook’s graphql client, relay, does not have this issue as it requires each component to explicitly declare its data dependencies.


> really only exists with Apollo

Citation needed. If two components call into the same data fetching utility for expediency's sake, and that utility queries data that one or both components do not need, you have this problem. What makes that uniquely likely with Apollo?


It’s more that compared to Relay, which is explicitly designed around preventing components using data they didn’t explicitly declare as a dependency, Apollo (along with most other GraphQL clients) doesn’t go that extra mile.

Whether it’s a React component, or a just a plain old function, Relay has mechanisms to prevent the kind of problem you’re describing. It has a steep learning curve, but it’s very well considered.


> Facebook’s graphql client, relay, does not have this issue as it requires each component to explicitly declare its data dependencies

In the scenario described, wouldn't this lead to the same problem because someone copied the code or reused a utility from another project and so they have at least the superset of those dependencies plus whatever new ones they added?


In many ways you also need to be a massive tech company to not create a massive scalability problem. The first time someone ships a shitty query to a large user base on a mobile app you are now dealing with the consequences of a frontend engineer creating a bad query you can not kill quickly any more.

Making scalable, well performing queries work is nontrivial, particularly with the current ecosystem of GraphQL libraries. The main workaround for this provided appears to be directly mapping GraphQL to an ORM.


I used to see GraphQL (and to an uglier respect Soap like interfaces) as complicated solutions to that problem you describe.

But more and more, I think Backend For Frontends solve this issue in a much better way. And of course that idea isn’t new and Yahoo for instance had that kind of architecture.

Frontend teams get to adjust by themselves a simple interface to their needs, and backend teams can provide more info through internal APIs with less restrictions than if it was directly exposed to the outside.


I'm not following if you think GraphQL is a bad fit still, but we used GraphQL with the BFF pattern, and it was nice to use from Frontend to BFF. The backend services would use REST or whatever appropriate behind the BFF.


I see GraphQL as unneeded if you already have a BFF managed by front teams.

Going with basic REST gives you simpler caching/optimisation paths, more straightforward mapping between the front request and the backend calls, and it makes it easier for other teams to look at what you’re doing and comment on/fix stuff as needed. GraphQL would be pure syntax sugar, and I’m not sure it would be worth the trade-off.


> more straightforward mapping between the front request and the backend calls,

I disagree, at least compared to something like Apollo Server or Hasura. The mapping is much easier, especially if you consider things like resolvers having parts of the schema going to different backend servers, API endpoints, separate caching, etc.

We tried to do this manually via a REST server, and found that we were just reinventing something like Apollo, but badly.


You can use GraphQL for BFF btw.


Do you have any reference material for the Yahoo architecture?


It was pretty basic so I’m not sure how much it was talked outside of Yahoo. I see this presentation http://www.radwin.org/michael/talks/php-at-yahoo-zend2005.pd... providing an overview, but otherwise the basic principle was to have each addressable web server host an apache with a routing module, and that module will map a request path to a cgi file.

With that structure you can have any number of layers with your front call and the different business abstractions all representated by an API (let’s say you want a user’s average engagement with a service, you’d hit the high level API, which will fetch access stats from another API, which rely on a lower level API which goes through another separate layer managing DB cache etc.

Most of these call are of course internal to a data center.


I think an other thing with graphql is it reduces friction when trying to discover what your API should be.

So what you can do is some sort of generative graphql thingie when doing your initial iteration, with the client hitting whatever is convenient (in that situation you'd just expose the entire backend unprotected).

Once the needs have gelled out you strip it out and replace the graphql queries by bespoke API endpoints.


In my experience, "let's do something non-scalable and obviously wrong while we're exploring the problem space and replace it with something better before shipping" reduces to "let's do something non-scalable and ship to production" 100% of the time.


So you are saying it works? At least all the production systems where we’ve done this work fine, they’re just inefficient, feel vaguely dirty, and are unpleasant to work on. They’re still bringing in boatloads of money though.


I think the risk with unrestricted access to your database via GraphQL is that it's potentially a very easy DOS attack sitting waiting to be abused, and potentially a security risk if there's some information you shouldn't be exposing (as a very easy example, allowing unrestricted access to a user database would reveal password hashes, reset tokens, etc. which should never be available in a API).

I'm a fan of YAGNI, but basic security and leaving your system trivially vulnerable to attacks are a couple of exceptions in my mind.


I just have never had this as a problem having worked on many APIs at many companies. Usually we decide what we want to work on and the frontend/full stack can read the documentation / chat with the backend engineers if it’s not clear. At no point is “discoverability” a issue


The discoverability I’m talking about is not about knowing what the API is, it’s finding out what the API should be.


100% agree that it’s about dependence on other teams. That said, I’d much rather that we were communicating across a well defined api boundary, rather than a graphql api. You could, of course, very easily do this with an api layer in the middle.


Nobody seems to get the idea of building software out of pieces with well defined APIs any more </rant>. I would say it's not possible to build large software without adhering to this principle but I seem to be proven wrong. You can build large poor quality software and just throw more people at it.

The other part about team dependence is very true but it also shows a lack of knowledge/thinking/care by whoever formed the teams. It seemed for a while Amazon had things right both in terms of boundaries of teams and in terms of forcing people to use APIs- not sure what they do these days.


This is one of the strengths of gRPC, it forces and centralizes the (mostly type safe) API design from the get-go.

Also tends to use a lot less bandwidth.


The biggest issue with GRPC is that it is only suitable for stateful languages (iow, languages that can hold values and share them between requests). GRPC is basically worthless for stateless languages and unusable. These stateless languages also don’t work well for websockets either, so it is what it is.

Until they solve the stateful part, I’m not using it or recommending it to be used anywhere. Bandwidth is cheap, type safety is overrated, and compute is expensive.


What's a "stateful language"? Can you give an example here? gRPC is orthogonal to whether an API relies on state or not.


Is this bait? Lol


What is a well defined API to access a lot of related datasets if you have 100s of external users, using it for 10s of different types of use cases?

Compare it to a database, what if you couldn't use random queries with SQL, but only had the option to call stored procedures?


It's the narrowest abstraction fitting those use cases. A database by its nature is a generic component. So sure, the piece of your software that's "SQL database" has a SQL interface, pretty quickly you'd want some abstractions on top of that around the different uses of that database.

The problem is when genericity diffuses its way into a large system it becomes impossible to maintain. How do you refactor a code base when everything everywhere is just SQL queries. If you want to change the schema how do you know you're not breaking anything? The short answer is you don't and so the software becomes incredibly brittle. The common workaround is testing but you can never test everything and now your tests also become coupled to everything else making things even more difficult to change.

The database in your example, while being generic is already an abstraction of sorts. Now if you're building lessay gmail the external users should see "create email", "get all emails", vs. issuing SQL queries to the database. That makes it easier to change the two pieces (client and server in this simplified example).


If that field isn’t populated aren’t you in the exact same spot?


Let's say you need to get a field back that is already in the database table, but that wasn't previously returned by the GraphQL endpoint. All you have to do on the front end is ask for it and GraphQL will populate it for you on the server.


If your GraphQL schema is just a mapping of database tables, in my experience you are in for a world of hurt in the future.


At my workplace they made this decision before I started and I can fully agree with this. It's essentially a typed REST without any of the benefits. No joins, everything is multiple calls away to perform a "full" query.

I don't even want to think about undoing this mess.


It's possible to do this without it getting painful, but you need to annotate the database schema with a lot of meta data.

We don't use GraphQL, but we do use an API that is mostly generated from meta data about the schema and permissions on a per field basis, with the ability to override on a per table basis.

To the API consumer it's invisible if they're referring to something that refers directly to a real database columns or to a method on a model class that doesn't correspond directly to the database (e.g. the user "password" attribute is

Effectively there are two schemas: the API schema and the database schema, it's just that the API schema is "prepopulated" from introspecting the database schema using Sequel (Ruby ORM), with the model classes translating between the two, with a synthesised default mapping.

The "API schema" includes more granular type information suitable for the frontend, and permissions, including type information returned to the frontend to provide default client side form rendering and validations (also enforced on the server, of course). It also auto-generates documentation pages with example data, inspired by Airtable's doc pages.

But key to avoiding what you describe is that these are all easily overridable defaults, and the permissions default to allowing no columns, so while the db schema introspection makes it quick to expose things where a direct mapping makes sense, it also makes it easy to avoid.

Unlike GraphQL we explicitly avoided allowing you to request arbitrary complex sets of data, but what you can do is expose queries by defining model metadata for them that either wraps suitable views or custom queries. We have a UI to allow us to define and store custom queries and views for e.g. reporting needs, so we can prototype new API needs in the browser writing just queries with some metadata annotation.

It gets us the flexibility of being able to quickly return exactly the desired data, while retaining control over the queries and complexity.


A world where the front end can access any database field it wants sounds like a security / privacy nightmare to me.

Of course there are ways to prevent data from being returned but that’s fragile.


This isn’t remotely a problem. Field by field granular security is trivial to implement in GraohQL


I have to disagree with you there. It is possible, but it causes other annoying problems.

For example, field-level security pretty much means every field could be null at any time. Depending on your graphql server implementation, this might cause an entire request to fail rather than just that field to be omitted, unless you change your schema to where everything is nullable.

Checking every field can also easily lead to performance issues, because it’s not uncommon for a large, complex graphql request to have hundreds or thousands of fields (particularly when displaying lists of data to a user).


Not to mention GraphQL wasn’t designed with security and user-state in mind. It was an afterthought that was bolted on, varying from framework implementation to implementation.


How the heck was that not on their minds from day 1? It's the most obvious question to ask about a project like that.


It’s from before the https-everywhere days, or around the same time letsencrypt was started up, IIRC. Back then, I feel like security wasn’t as big of an issue, at least for less sensitive things. Like literally the entire site would be http until you got to checkout and the only reason you had the certs was to be PCI compliant.


GraphQL is mostly concerned with the query semantics.

A proper solution to security/privacy issues should have sensitive data never reach the outermost GraphQL layer.

So the problem is with the existing tooling that enables GraphQL implementations, but like anything else, if that tooling is deficient, the entire approach is on the shaky ground too.


> unless you change your schema to where everything is nullable

At my current job, this was done before I was involved. It isn’t a deal breaker, but it throws away one of the best features of GraphQL.

In the end you just have every client implement the rules that should have been in an API tier (if they are competent), or worse no validation that gets you a giant mess.


How does GraphQL help here?


Assuming the backend actually supports mapping of that particular field.


For external users of the API this can be quite helpful when you’re looking for the password column on the users table.

For some reason I don’t think graphql actually works this way. Can’t quite put my finger on why allowing access to any column on a table might be a really bad idea.


Putting passwords in a database, and that database behind some kind of service that allows queries, is a stupid mistake that can be implemented with SOAP, CORBA, a remote shell, or any other protocol or API style.

I don't think GraphQL makes the problem worse except by encouraging experimentation by putting an unusually powerful query language in the hands of the users


Ancestors of your post are suggesting exposing entire DB schemas (I would assume mechanically). While that could also be the case in other protocols, typical an IDL is used to separately define the API layer. Of course it’s completely possible to generate a WSDL, etc. from a DB schema, in practice I’ve never seen it done.


My point is that passwords shouldn't be stored in the "normal" database where some clever architect might expose entire DB schemas to external access.

If clever architects manage to expose the carefully segregated database of the small and secure authentication module, they cannot claim it was an accident or someone else's fault,


>Can’t quite put my finger on why allowing access to any column on a table might be a really bad idea.

Privacy


Why not just query the database directly then?


+1 This is it. Great for internal API's, not so much for public facing ones.


Whether it was the intention or not, I find GraphQL solved a fascinating problem: it let front end developers move faster by greatly decoupling their data needs from the backend developers.

Backend developers describe the data model, expose it via graphql. Front end developers, often ones who never met those backend developers, can see the data model and just use it. They can change what they're querying on the fly, get more or less as they see fit.

It lets everyone move faster.

But as a backend developer, I actually fucking hate it, myself.


I get specialization, but are there any other good reasons to divide product teams between frontend and backend? I guess it also helps establish patterns and contracts, but I think those are only helpful above a critical mass that I haven’t reached in my career yet.


It depends on the kind of application and scale. Consider a large and complex application like Discord or Figma. Past a certain point, it's hard for anyone to know how every single detail works.

You should probably be comfortable enough to work with both ends of the spectrum, but specialization allows you to do a much deeper dive into complex subjects.

A backend engineer probably has a much deeper understanding of every little nuance of their prefered database. A great backend engineer can make sure that you're getting near-optimal performance from every important query.

A frontend engineer probably knows about various UX techniques along with how to avoid unecessary reflows and repaints. A great frontend engineer can implement a UI toolkit as well as advanced techniques such as windowing.


Right, that’s specialization. IMO those people still belong on the same feature implementation team for most organizations out there.


The reason is to scale teams. It’s not the only way to do it—you can also have vertical teams—but it’s a common one because frontend and backend have different technical considerations. The downside is the product can lose cohesion as developers get tunnel vision. Of course all big teams suffer from a version of that problem depending how the lines are drawn.


In a small organization there isn't generally any reason to divide the teams between front and back end. As you've alluded - once you have many clients you'll want to separate responsibilities in order to increase velocity.


Frontend teams are often feature partitioned at least in larger orgs. There will need to be some level of feature level backend knowledge to be had somewhere, but backend problems are often feature agnostic. Many companies conflate backend with platform, which have subtle differences, but end up working with similar results. Specialized backend teams work to develop a really good "platform" feature while frontend teams focus on developing customer/product oriented features.


This is something I’ve wondered as well. Coming from the military and occasionally working with spec-ops, I would say having a few “full stack” teams would be the way to go. I am just a lowly dev though, so what do I know?

The separation of front/backend has always been mildly entertaining to me and I’ve worked on both teams. Btw, if you ever want to cause a political mess, just submit a PR to add a new API endpoint to the backend team that “doesn’t have the time” to work on it. Woah boy, they will get mighty pissed. As a backend engineer these days, it would be a blessing to get free work from another team… I don’t know why they were so pissed that one time.


Well, if you are truly wondering, I think I can give you some intuition about "why they were so pissed". Obviously, I don't know what were the facts of the situation, and if they really should've been pissed, but I can explain the typical mindset.

The main idea is that writing some code to achieve any particular effect in the system is typically easy. But writing code, that is efficient and maintainable isn't easy. So, there's a team X, which has people working on some specific system. They own the code. To them, their work isn't quite about "implementing requested features". It is about inventing proper abstractions that both reflect the logic of the requested feature and reasonably anticipate the logic of any future feature requests. They want to avoid having 2 implementations of the same thing, they want every piece of code to be idiomatic to their system, etc. And they are right thinking like that, BTW. Every new developer they get is treated with some suspicion at first, and when he learns the idioms of the system he becomes a honored member of the team X. If he fails to learn them, he gets fired or passed to another team, where he may turn out a better fit.

So, for the members of team X, they are professionals, who know how to work on the product and on the system X. Members of other back-end teams are probably not, even if they are good devs otherwise. Some frontend dev — doubly so. Some junior frontend dev coming from military or helpdesk or whatever — triply so.

So, you may think that you are a great and charitable developer, who just implemented a Feature. But to them, you are a lowly ape who made a wobbly hut out of some sticks and leaves that is going to fall down now any moment, and it's going to fall down on THEIR heads (and you will be long gone).

Worse than that, they understand, that other non-engineers (like their manager) also are prone to mistaking a wobbly hut for a Feature. And you basically humiliated them in front of these people by "solving" their problems (while in fact you created more problems). So it gets political here. In fact, because of that, even if the above is not a fair description of your work, they kind want it to be fair, they want you to fuck up, because it at least makes it easier to explain why your help wasn't a real help.

And, in all fairness, it is kinda unlikely that a guy who is new to a codebase didn't fuck up in any way, even ever so slightly. Especially if that's a kind of guy who doesn't understand why dedicated back-end and front-end teams exist.


> BTW. Every new developer they get is treated with some suspicion at first, and when he learns the idioms of the system he becomes a honored member of the team X. If he fails to learn them, he gets fired or passed to another team, where he may turn out a better fit.

Oooh, that's an interesting observation. This was so long ago, before I really knew about this attitude. Since then, I've been on these teams and despise that attitude. I didn't even know that attitude existed back then, so this is indeed a possibility.

> And, in all fairness, it is kinda unlikely that a guy who is new to a codebase didn't fuck up in any way, even ever so slightly. Especially if that's a kind of guy who doesn't understand why dedicated back-end and front-end teams exist.

Hah, they couldn't find any fault with the code, the unit tests were even better quality than their own. I also submitted several other PRs fixing bugs that I discovered while writing unit tests. Their reason for not merging the code, after reviewing it, was that the implementation "didn't seem scalable" despite including performance tests showing that it was both faster and used less resources than some of the more popular API endpoints.

When I joined, they kept having GC problems and I pointed out that they were using the Desktop GC method instead of the Server mode GC (this was C# 3.x?) and they didn't even know that that was a thing. They didn't like how some frontend engineer seemed to know more about C# than them.... I imagine that it was a combination of a lot of things, me knowing more about their language than them and not being on their team, plus submitting PRs "showing them up."

This was my first time working at a company with more than 10 devs, so I was used to just getting shit done and not worrying about politics. These days, I know better.


They were likely pissed because they were afraid it would make them look bad to management - "How come no one on the backend team could find time to build this, but one front-end guy managed to despite his regular workload?"

It's an easy conclusion to get to, whether justified or not.

No one likes being made to look incompetent, regardless of whether they actually are.

I have the impression you didn't ask for permission before you did it - the dynamic is wildly different if you start things off by asking if they'd be okay with you taking some time to build it, then involve them in your process as much or as little as they want.

If that's what you actually did, then my analysis is way off.


I think you are saying why not combine specialists on one team vs the “everyone is fullstack+devops” amateur hour dystopia that is becoming all too common?


Back in the day we call this role Webmaster. Being able to manage your server, write your code and design the website was what a true developer tried to achieve.

It is strange to see developers preferring to stay in their isolated environments and not wanting to touch the entire stack.


It's not strange at all - it takes months of work to get productive with insert whatever tech stack here even when it's within your experience domain. Problem domains are really separate. Toolchains and languages are different. It's already hard to find people competent on one stack/field - hoping to find a team of competent "full-stack", in the broadest sense of the word, is probably prohibitively expensive.


This actually made sense back in the day. Now there's significantly more complexity for each part of the stack, tooling, distributed design patterns for scaling, etc. We don't really have "websites" any more, for example. We have apps that run in the browser.


> the “everyone is fullstack+devops” amateur hour dystopia that is becoming all too common?

What a weird thing to say. That was the original state. At some point people started splitting things up because they felt that would be better (or they just weren’t capable of grasping more than one thing?), but I’m extremely sceptical of all this specialization.


I think we’re all amateurs at some part of the stack. I am not the CircleCI dude in my current gig, some other competent engineer is, but I’ve been the Jenkins dude in the past because I cared about it the most.


You can have N frontends for one backend. If you need a new iOS app you will probably hire a team of iOS developers, not have all of your product teams learn Swift.

If your API looks like this...

  /ios-app/v1/landing-page
  /android-app/v1/landing-page
  /android-app/v2/landing-page
  /windows-mobile/v1/landing-page (legacy)
  /web/v5/...
where each platform has its own subtly different UI structure, the ability for frontend teams to get basically an arbitrary JSON structure of their choosing starts looking worth the extra work on the backend.

You might not encounter this problem at any point that's fine - there are other ways to avoid it, like having a cross-platform codebase. I have "hand-rolled" similar solutions to the GraphQL field selection before, and I would use the GraphQL protocol if I were to do it again today.


It could be the contrived example, but REST URIs are supposed to represent resources, not UI pages or elements. When the endpoints start to become coupled to the UI the backend can get messy, as you described, very quickly.


> good reasons to divide product teams between frontend and backend?

People specialize in different things. A great React developer may not be a great Java developer, and vice-versa


An intermediate Java and React developer is more than the sum of the parts. Especially when considering a whole team.

You may need one or two really great React and/or Java developers.


From a management perspective, the fiction of the full stack developer that is equally skilled at everything is the easiest. You stick with that until you complicate your architecture (wisely or not) to the point where having specialists outweighs having to manage multiples queues of work and dependencies.


Worse approach imo.

Nowadays a full stack dev is an intermediate Fe dev, with junior backend skills. He will make your backend un-maintainable. Get a proper master on a proper contract rate to design your architecture.


To me it's a weird way to go about this decoupling. Another way is you can just keep your own view-model client side and abstract the backend data with that.

FFBs and GraphQL is a way to tightly couple to a backend system and then have that backend system loosely coupled.

I guess its all 6 of one, half-dozen of the other, but I usually prefer to just handle things client side. You can maybe get less data transfer optimization but that's down the road from the fast development stage, anyway.


I thought it was supposed to do this, but then discovered that it has no way to express joins.

Has this been addressed? I don't see how you can decouple the back-end data from front-end queries without that.


You can do something like this. This query can be created and run on the client:

``` const SAMPLE_JOIN_QUERY = gql` query ($main_data_id: String!) { mainData( main_data_id: $main_data_id) { id main_data_field_1 main_data_field_2 main_data_field_3 related_data{ related_data_field_1 related_data_field_2 related_data_field_3 } } } `; ```


https://news.ycombinator.com/formatdoc may interest you

    const SAMPLE_JOIN_QUERY = gql`
    query ($main_data_id: String!) {
      mainData( main_data_id: $main_data_id) { 
        id main_data_field_1 main_data_field_2 main_data_field_3 
        related_data {
          related_data_field_1 related_data_field_2 related_data_field_3
        }
      } 
    }`;


Thanks!


in other words, it's up to the folks writing the resolvers to manifest and implement that join as a nested field.


Which means a lot of the time they end up just caching as hard as they can and hoping that's good enough.

(which is often, honestly, an entirely rational decision in terms of prioritising limited resources, but still makes me sad)


Dataloader does this IIRC


Right, but on the backend someone had to think ahead of time that somebody would want to JOIN between those two types, and remember to put the field in place, and implement the JOIN.


Curious as to why you hate it specifically. Because what you could be doing is exposing every table / field automatically based on permissions (which you could set up a system where you don't even have to be involved).


because either the boilerplate is massive or the libraries do so much for you that you have to specialize in understanding the libraries magic - front-end plus back-end code for graphql is almost always more than a traditional REST api and I mean a lot more code, not just a bit more, so more code is strongly correlated with more problems. The exception is when you use heavy libraries that have magical APIs. Then you end up with teams who understand the API and have no idea how graphql actually works, which is probably an even worse problem.


What tooling are you using that requires a massive amount of extra code? You need to define the schema and write resolvers, but that's sorta similar to what you might do in REST on the backend.

On the frontend, you have a choice to use some of the heavier libraries that support all of the features (like subscriptions) - but otherwise, you can just POST a gql query to the server and it will return a blob of json, which really isn't so much more than REST.


Why use graphql at all if you are going to use it just like a traditional REST api? You don't get much of a benefit from the client selecting which fields it wants, the backend probably fetches the entire DB row anyway so why not just send the whole thing over?

The limitations of the query language make code size explode the moment you step outside simple toy examples. It doesn't have any concept of a JOIN, or of the actual relationships between your types (graphql has no concept that me == me.parent.child). You end up writing data loaders for every type so that loops in your schema can be resolved efficiently.

Managing permissions is so much more of a pain compared to REST because exactly what data is returned is so much more dynamic. If you have some confidential data nested 10 layers deep in the query, you get two choices. Either fail the entire query with a NotAllowed based on one deeply nested field that the client maybe does not even care about, or you have to make your schema super loose and make every single field that's subject to permission management nullable. So much easier on a REST endpoint because the response is more constrained.


You use graphql when you have many consumers of your data, whether other teams at your company or external data partners (which is how my team uses it). What it does is make it so that you don't have to provide a bunch of custom endpoints for these users, they can get exactly what they need without your help. You're also able to get performance gains dependent on the implementation.

Our code size for our graphql endpoint has remained totally unchanged for the past couple of years. It took only a few files (of admittedly complex code) to automatically set it up so that it would automatically provide all models via the graphql schema (and a separate permissions implementation restricts access at each level of the schema). It updates automatically whenever we add new models or permissions. This is built on top of Rails and the graphql gem.


Honestly it's mostly just lack of familiarity, which is getting better every day.


e.g. postgraphile


It sounds like it is promoting a siloed cogs in the machine type of work ethic. Where you are either front end or back end and no one is thinking end-to-end about the system.


I think the causality runs the other way. Once the frontend had gotten so complex that it required a specialized team, solutions arose to reduce the back and forth necessary between frontend and backend teams.


Sr enough developers who's role expands beyond a single team, architects, product managers, product owners, the list goes on for the roles of people who are often task of thinking big picture about the health and "end-to-end" picture of any given software project. Your narrow synicism makes me assume you don't work in a company that has a large dev org. People specialize and if you want to be the learn and do everything person, you'll find that you're doing less and learning more which isn't a good fit for most orgs.


You are right I have worked in relatively small companies (and "bigger small" companies that were not doing web).

My concern is not specialization which I think is necessary for a larger company. It is more the technical solution of "here is GraphQL now your teams don't need to talk and you don't need anyone thinking end to end". I can't believe that is helpful.

I may have created a strawman though?


That's generally true for sizable companies. Small companies can and do use full stack devs.

Segmentation makes some sense but the industry is lacking end to end thinking as you point out.


Why do you hate it? What tooling are you using? I found it fairly painless in Python - Graphene/Flask.


If all you do is expose simple models, it's fine. But then not much different than an auto-generated REST-api. But if you want to query deep, list of childrens etc you quickly get into queries that are very hard to write on the backend (n+1 issues quickly pop up etc). To solve those you need to write complicated loaders, which all should be very general in nature and thus you can't rely on two fields backed by the same data sharing a query without doing something special. Which is much more hassle than just writing whatever join you want for a tailored endpoint.


The N query is the general case which devolves to the scaler query with a list of ids with only one id...


I joke mostly. Coming from a REST based background it was really foreign and convoluted to me.

Until I understood the point, the organizational decoupling. Then it clicked why it's great.


Be careful with anyone with a take that says some technology is 100% bad always. Given enough experience / skill you can make any technology fairly enjoyable so I've only ever seen mixed reactions at worst from people giving things a fair try.

GraphQL is a way to describe not only your API but also the entities and relationships in it. This enables certain useful things for client heavy applications, like cache normalization. If you look at clients like URQL they enable high quality features in your app that are otherwise extremely difficult.

You can also do this with JSONAPI but the GraphQL ecosystem is more developed.

Setting up GraphQL to minimize its rough edges is incredibly difficult. I've currently landed on a combination of Pothos + Genql + URQL to enable me to do everything in typescript instead of untyped strings.

It takes very high skill to use GraphQL well. Few teams get there because they don't have the upfront time to do all the research.

But if you pull it off it can be an incredibly productive system that is friendly to iteration and refactoring. I can send you some content we've produced on this if you're interested.

That said, if I'm not working on a client heavy app, I'd just use a less featureful RPC framework.


> Be careful with anyone with a take that says some technology is 100% bad always.

This isn’t that though; the first sentence starts “GraphQL is great, but” and then the post lists first “the good” and then “the bad.” Even the provocative headline hedges with “kinda.”

I wish there was more of this sort of balanced discussion on HN. There is a tendency among devs at least in public toward trying to get others to use the tech they use and are excited about, which is understandable, but everything involves trade offs and it would be nice to hear more of those up front (as opposed to one day “mongo is the bomb” and the next “actually mongo is terrible to back to postgres for everything).


was referring to some of the replies


Ah ok I definitely misunderstood, thanks for clarifying.


> balanced discussion

while the discussion can be balanced the real world outcome is normally binary: use it or drop it.

i will not start investing huge amounts of time to learn graphql if it has very specific use cases for specific environments. so i naturally look for red flags and objectively negative experiences to see if those might be the roadblocks i would run into 2 months down the line.

imagine a PM coming in all happy "i know nothing about graphql besides the hype but i think it's a great fit for our next project". where will balanced discussion take you there?


Agree with everything here, but something that often gets missed is that you don't have to use all that GraphQL enables from day one.

It is perfectly fine to start with an early implementation that treats GraphQL as mostly an RPC, with only resolvers for Query & Mutation types. You still benefit from GraphQL's type-safety, batching and code-generation.

Once you have more familiarity with dataloaders, query complexity etc. update your output objects to have links to other output objects building the graph model.

The issue is that too many people get fascinated with GraphQL early, then build deep & complex topologies and expose it in inefficient and potentially insecure way.


I love consuming graphql as a client. But writing resolvers and all that stuff on the backend? God, I hate it!


I don't know your language of choice, but in the JVM ecosystem, Netflix DGS is so damn simple to build new resolvers.


It's very enjoyable with python. Especially given integrations with frameworks like django.


Hasura :)


Have you every tried to version your permissions on Hasura? Not cool. Product polish is amazing, and I love the postgresql integration.


Nope, I haven't, here's hoping I won't need to!

First time thinking about the situation, sounds to me like you'd need to just make a new set of roles no? I can't imagine they'd have version support for that, not like the underlying datastore does


Interesting point. What sort of approaches out there do you know about for versioning permissions?


> Be careful with anyone with a take that says some technology is 100% bad always.

On the flip side, you should also be careful of anyone who says some technology is 100% good always. It's far more common to see people talking up the advantages of some trendy new technology without ever mentioning the downsides. All technologies have tradeoffs.


> Be careful with anyone with a take that says some technology is 100% bad always.

THIS 100%.

> It takes very high skill to use GraphQL well. But if you pull it off it can be an incredibly productive system that is friendly to integration and refactoring.

I could not agree more. It's like any other piece of tech: once you internalize the mental model and are able to translate those abstractions in your language of choice everything clicks. And then it's hard to imagine going back to something more "primitive" (i.e. what's conventionally called "REST").

After building "RESTful" APIs for years I can confidently say GraphQL (with a decent implementation) is a step up across almost every possible dimension (performance aside because of the additional parsing).


> It's like any other piece of tech: once you internalize the mental model and are able to translate those abstractions in your language of choice everything clicks.

While this is true, I think the ultimate assesment of a technology is how easy is it for someone skilled at doing similar work to internalize the model and abstractions.

A tech stack can become really successful only if this is easy and relatively quick, otherwise, it will meet a lot of resistance. Partly because it's hard to master, but partly because so many people will be misusing it (which makes an even bigger annoyance for someone who's trying to get to a proper mental model).

As such, I've come to appreciate only models that majority of developers can easily get right on the first go: or rather, models which are hard to get wrong.


Eh I think "rest for external API access, graphql for internal frontend use" is probably a good thing.


> Be careful with anyone with a take that says some technology is 100% bad always. Given enough experience / skill you can make any technology fairly enjoyable so I've only ever seen mixed reactions at worse from people giving things a fair try.

Completely agreed. Without knowing the team experience, greenfield project or not or in general more information about the task at hand, how can anyone say GraphQL is good or not?

One thing I've noticed among some people who've failed to move up in their career is that they carry these extreme opinions due to a proper understanding or a bad experience. Right tool for the job and all that.


> Given enough experience / skill you can make any technology fairly enjoyable

Have you never used MongoDB?



The other thing to note is that early on the default configuration was optimised to score really well on trivial benchmarks rather than production workloads - including having important safety features turned off.

A crashing MongoDB instance in default configuration was more likely to lose data irrevocably than a MySQL 3.23 MyISAM setup.

(note that while I still don't particularly enjoy using it, post-WiredTiger MongoDB is a different story so take this as a criticism of the people making choices in the early days, not at all of the current state of affairs)



That’s a great thread. It mimics my (admittedly limited) experience with MongoDB and it’s interesting to hear that wasn’t an outlier.


>Be careful with anyone with a take that says some technology is 100% bad always. Given enough experience / skill you can make any technology fairly enjoyable so I've only ever seen mixed reactions at worst from people giving things a fair try.

So what does this mean?

You're saying that in the universe we live in there is absolutely nothing that is 100% bad always. Everything is good for something? There is no concept of bad or obsolete things because it's all good for something?

Let's restrict this to programming languages and frameworks and apis.

Are you saying that in the universe of ALL programming languages, ALL frameworks and all APIs, None of them are at all bad and they are all good for something?

I don't agree with this sentiment at all. In fact I think it's a sign of two possibilities:

1. that the person saying it is highly biased and unable to detect things that are genuinely bad.

2. The person saying it is just being temporarily illogical, there are clearly things in the programming world that are bad. He knows this but is so biased that he's incapable of processing this concept while promoting his favorite language/api/framework.

Scenario 2 is the most likely scenario here. Not saying graphQL is bad. But to love graphQL so much as to say Nothing in the universe is actually bad?

Let's be real, I am not against graphQL. However you cannot actually say that people against graphQL have invalid opinions because there is nothing in the programming universe that is definitively bad. This argument does not make any sense at all.


The point is that “bad” isn’t a useful descriptor of anything regarding their real-life applications, because it simply doesn’t mean anything. Without more context, saying something is bad is just saying you dislike it with intent to present it as objective rather than subjective.

For example:

1) “Haskell is bad because it’s too theoretical” 2) “Haskell is bad in corporate environments, as its roots in mathematical and academia make it harder for people to get productive with it compared to something like Java or C#”

The difference is clear. In my opinion it’s best if people who care about what they’re saying avoids #1, and instead frames their criticism like in #2.

Note: those examples don’t reflect my actual opinion on Haskell, it’s just something I came up with while writing this.


Hard disagree.

>The point is that “bad” isn’t a useful descriptor of anything regarding their real-life applications, because it simply doesn’t mean anything.

This is just a complicated way of saying "Bad things have no meaning and don't exist in the universe."

Without getting too pedantic, in general, nobody agrees with this concept. Sure if you get pedantic you may find a couple people in this world who enjoy punching themselves in the face, but in general the overwhelming majority agree that punching yourself in the face is a pretty bad thing.

Note: Punching yourself in the face is just an example of a universally "bad" thing. I'm not personally against punching yourself in the face, it's just something I came up with while writing this.


Maybe I failed to express myself properly, but my point is that saying “X is bad.” (emphasis on the period) is not really saying anything. It’s much more productive if you explain why, how and in what environment X is bad, either before or after, like I did in example #2.

In my experience when someone says “X is bad”, the response is often either “haha” (which the subject then changes), or “why” (which leads to person #1 actually saying what they want to say). I’m personally not interested in someone’s remarks about some technology completely devoid of context or nuance, and would rather hear about their opinion on such technology in tangible scenarios.


>Maybe I failed to express myself properly, but my point is that saying “X is bad.” (emphasis on the period) is not really saying anything.

This logic also works for "X is good." or "GraphQL is good". This doesn't really say anything either and is an equally garbage statement following your logic. But your biases focus on the "bad" because you have a bias towards GraphQL.

Either way I don't agree. Saying something like criminals are bad is not an invalid statement.

If you want an explanation you can ask for it. If you don't care to know about the explanation then you don't need to ask for it. But just because somebody makes a statement without an explanation doesn't automatically make it invalid.

For example "The plane is about to crash, please pull up." This is a statement without an explanation (emphasis on the period). Should I demand an explanation or comply without one? In your words, was this statement "really saying anything?" Yes it was.

When you come to threads on HN it's mostly people looking for confirmation of their biases. They don't realize it, but almost everyone is doing this. If you weren't biased you would ask for deeper explanations. You would try to unravel the other persons reasoning and understand it in such a way so that you find a mistake in his understanding or your own. That's mainly why I'm here, but this thread is littered with posts following the same logical path as you.


There are way too many assumptions in your post. Yes, you're right that I like GraphQL, but:

1) Nowhere in my comments did I say that's limited to negative comments. I think "GraphQL is good" is just as useful (meaning not at all).

2) "Criminals are bad" is not an invalid statement, and neither is "GraphQL is bad" or "GraphQL" is good. But if the purpose is to discuss criminality, and not just add noise to an ongoing discussion, it is also a useless statement. Imagine there's a debate panel going on, someone in the crowd stands up and says "criminals are bad!". Where does that lead the conversation?

3) "The plane is about to crash, please pull up" is an expression of fact, not an opinion, and not even something that warrants or is said in a discussion so I don't think the comparison makes sense. Either way, "GraphQL is bad" is an opinion, not a fact, and thus needs more context to be useful in a discussion.

I'm not going to acknowledge the last paragraph because I'm presuming good faith from you, and I'd rather not turn this discussion into speculation about other comments in this thread or why you're here.

That said, you're definitely right that I'm biased towards GraphQL, but I think we're having different discussions if you think we're discussing GraphQL's merits.


>Where does that lead the conversation?

It's not about leading the conversation some place. He's under no obligation to lead the conversation to a place you want it to go. If someone says something different, I don't dismiss the statement. I follow up with a question. You didn't. YOu simply made a broad statement dismissing all queries saying "X is bad" as invalid and you think it's up to the person stating something to explain. No. If you want an explanation you ask for it. But the statement by itself isn't invalid.

However you completely dismissing the negative claim was invalid in my opinion.

>But if the purpose is to discuss criminality,

Obviously this is an example not a segway into criminal law. I am showing an example of a statement that is true independent of explanation. True statements are not to be ignored even when they lack explanations. That is the point.

>"The plane is about to crash, please pull up" is an expression of fact, not an opinion, and not even something that warrants or is said in a discussion so I don't think the comparison makes sense

You can't automatically say something is a fact. It's very possible things like this are an expression of opinion. The copilot observes sensor readings, he thinks we're about to crash. The pilot observes sensor readings he see's no such indication of an impending crash. This is a realistic possibility. The ounter to this is also true. You may assume GraphQL being bad is an opinion, but it's possible that it is a fact.

Let me elaborate on that. What if the person who hates GraphQL is actually expressing a universal fact? But like the pilot you have a differing opinion because you "misread" the sensor readings. Instead of taking the cautionary approach of pulling up and subsequently listening to the copilots reasoning you dismiss a statement because it has no explanation.

The point of this example is to show you a very obvious scenario where it's highly unwise to dismiss a possibly True statement simply because it lacked an explanation. That is my point. You are dismissing a statement that has the possibility of being factually true. And you are saying you don't care whether or not it's true or not if the statement has not auto generated explanation you will dismiss it instead of inquiring further.

>I'm not going to acknowledge the last paragraph because I'm presuming good faith from you, and I'd rather not turn this discussion into speculation about other comments in this thread or why you're here.

fine. The point of me bringing it up is to not make this seem like a personal attack. But to frame my reply as a universal problem among all proponents of GraphQL that are responding in this thread. Basically i'm just reading people Gushing about how great GraphQL is and not exactly addressing why it's also despised by many on HN.

>That said, you're definitely right that I'm biased towards GraphQL, but I think we're having different discussions if you think we're discussing GraphQL's merits.

We aren't, not explicitly. I'm a neutral party with no opinion either way, I'm here to find a side to join. However reading your post and seeing that you're a proponent of GraphQL I'm criticizing your reasoning as unconvincing. Basically, Someone said GraphQL was bad, and your reasoning was all statements of the query "X is bad" should be dismissed.

I responded to explain to you why I didn't find your reasoning valid. That's all.


Hmm, I feel weird reading all this criticism of GQL. It reminds me of when our place switched to it and I was constantly slagging it off until my friend/colleague said "do you actually hate it or you just don't understand it?".

Default hostility to new concepts and frameworks can save a lot of time, energy and mistakes in software but sometimes for some use cases the new (variation of an old) solution can be superior.

We use it as the API we expose for our React and mobile clients and it's just, so good. I'd never want to consume it for a non-FE client but it's night and day versus stitching the results of multiple API calls together using some godawful chunk of mess like Redux.

We have a C# backend and Typescript frontend. We write our backend resolvers of the form `public async Task<SomeResultType> GetSomeNamedField(TypedParams pq)` and it just works, Apollo generates type safe client code and we define the schema in a single place. We still write backend code to implement each resolver method, exactly how we did in a normal API but... that's just the same.

I wonder how bad other backend devx must be for all these people to hate it, it seems more like a language specific implementation flaw than a genuine problem.


You haven't actually described any of the unique parts of GraphQL though. Generating a typesafe API whose schema is defined in a single place is trivial with an OpenApi spec and a client generator

What I've noticed is people get their first taste of a type safe api and automatic client creation via GraphQL and don't understand that exists without it.


> What I've noticed is people get their first taste of a type safe api and automatic client creation via GraphQL and don't understand that exists without it.

I mean, yes, you can technically write any project in C if you're smart and dedicated enough, but data scientists still use Python because it's easier to work with for the things they need to do. The fact that GraphQL is inherently safe, while REST is inherently not, is why people like GraphQL. OpenAPI is hardly the standard in Rest APIs.


I think it is the other way around. REST inherently only offers, what routes you implement, nothing more. In that sense it is "safe". There are frameworks like "Rocket" in Rust, which make things typesafe from the moment a request arrives at your route's handler. While GraphQL requires you to implement who can access what, because you allow the frontend a lot of freedom to formulate queries. This is inherently unsafe.

Perhaps we are talking about different kinds of "safety" or "aspects of safety"?


no I'm just wrong, sorry!


Some other bad things:

- Makes caching more challenging since there are now more possible permutations of the data depending on what query the client uses. A hacker could just spam your server's memory with cache entries by crafting many variations of queries.

- Makes access control a lot more complicated, slower and error-prone since the query needs to be analyzed in order to determine which resources are involved in any specific query in order for the server to decide whether to allow or block access to a resource. It's not like in REST where the request tells you exactly and precisely what resource the client wants to access.

- Adds overhead on the server side. It requires additional resources to process a query rather than just fetching resources by ID or fetching simple lists of resources. A lot of work may need to happen behind the scenes to fulfill a query and GraphQL hides this from the developer; this can lead to inefficient queries being used. I have a similar complaint about database ORMs which generate complex queries behind the scenes; this makes it difficult to identify performance issues in the underlying queries (since these are often completely hidden from the developer). Hiding necessary complexity is not a good idea... Maybe worse than adding unnecessary complexity.


It shifts the complexity to the server side. The additional logic you are describing currently lives on the client, where it's harder to update and likely duplicative across platforms.


> - Makes caching more challenging since there are now more possible permutations of the data depending on what query the client uses. A hacker could just spam your server's memory with cache entries by crafting many variations of queries.

You could use something like https://stellate.co/.

> - Makes access control a lot more complicated, slower and error-prone since the query needs to be analyzed in order to determine which resources are involved in any specific query in order for the server to decide whether to allow or block access to a resource.

Hasura and Postgraphile can do this - in the case of Postgraphile it obviously requires Postgres.


If the solution for caching problems turns out to be a hosted API proxy then there are still not enough tools available. If you put some third party infrastructure in front of your API then your availability is exactly that company's availability.


You can cache the objects in the query by ID. And then reuse them across a number of queries.

> It's not like in REST where the request tells you exactly and precisely what resource the client wants to access.

It can be. You can have a query that does `getObject(id: $id): Object`.

> Adds overhead on the server side.

Yep it pulls a heap of complexity around data fetching, synchronisation, and data modelling from the client to the server.

As it requires both the client and server to come to some agreement about a shared data model, it can appear as more work up front. But it enables a decoupling of the client and server such that the client can make requests for new use cases with the existing shared data model.


My usual experiene is that people use GraphQL wrong. GraphQL's primary use case is to homogenize access to a bunch of heteregenous backend services. If you find yourself just taking your Postgres database and creating a 1:1 mapping between your tables and GraphQL, this probably isn't a good fit as you'r ejust adding another layer for no reason.

> No clear path for Api versioning

GraphQL came about as a way for mobile clients to call backend services. At Facebook, once a version (of th emobile app) was released, it was essentially out there forever. Some people would simply never upgrade until they absolutely had to.

So the point of GraphQL is that you want to get away from thinking about versioning your API and cleanly upgrading because you probably can't. You can do versions but you don't have clean divisions. You'll mark a given field as "since v2.1". And fields that you ahve added can basically never be removed. The best you can do is make them return null or an error.

So if you want to do versions it probably means you have control over the server and the client such that you can deploy them almost simultaneously. If so, GraphQL isn't really designed for your use case. If not, get out of the mindset that client and server versions can move in lockstep.

I will say I think GraphQL made one mistake and that's baking in string values into the API. You can't change a field name without breaking your API. Same with enum values.

Protocol buffers (including gRPC) instead went for numbering. The name is just a convenience for reading the IDL and data definitions and for code generation but it doesn't translate to the wire format at all.

This can have downsides too but they're fairly minimal. For example, if you accidentally renumber your enums by inserting a new value in the middle, the whole thing can break (side note: always explicitly number your enum values in protobuf! That should've been the only way to do it).

Another issue is that fragments seem like a good idea for code reuse but they can get really out of hand. It's so much easier just to add a field to an existing fragment. If that fragment is used in a bunch of places you may find yourself regenerating a ton of code. You will never be able to remove that field from the fragment once added.

Disclaimer: Ex-Facebooker.


> GraphQL came about as a way for mobile clients to call backend services. At Facebook, once a version (of the mobile app) was released, it was essentially out there forever. Some people would simply never upgrade until they absolutely had to. > > The point of GraphQL is that you want to get away from thinking about versioning your API and cleanly upgrading because you probably can't. You can do versions but you don't have clean divisions. You'll mark a given field as "since v2.1". And fields that you have added can basically never be removed. The best you can do is make them return null or an error.

This nails it. For distributed apps where a client might never be updated, you can't really change your schema if you want to guarantee that your app works for everyone. You can build in a mechanism to prompt users to update to a later version, though, and that can be very effective.


My company has many backends federated together, but a monolithic, web-based frontend. It’s actually really easy to remove a field from graphql.

1. Remove all uses from the frontend. 2. Deploy. 3. A day later, delete it from the schema.

If deleting it causes relay compiler errors, go back to step 1.

(The less lazy way to do it would be to actually pull some stats about how long-lived frontend bundles are)

Not being able to delete fields only really applies if you have a huge number of clients that you can’t easily force to update on a whim. Plenty of folks just have web clients.

My company doesn’t have this, but I’d love to get per-field usage stats about our schema.


That affirms my point: you have complete control over the front end.


We recently had to design an HTTP API, and we wanted to have as much automatic stuff as possible. I mean:

* Autogenerated documentation

* Autogenerated wrappers for scripting languages

* Autogenerated validator for requests and responses

For a REST API, you can get most of these things with swagger or stuff like that, but clearly it's an afterthought. If you have a schema, it's all much more natural and elegant.

But the most important thing you get with GraphQL is batching. For our use case (a decompilation pipeline) if you make 10 requests one after the other or 10 requests altogether it makes a huge difference in terms of performance.

If you need batching and design a REST API, for every nice endpoint you have you need to make a bulk version of the API. You're likely going to do that POST'ing a JSON. Now, once you're at that point, you're reinventing the wheel with six sides.

If your backend is in C/C++ and I suggest to make a C API for Python and use ariadne:

    https://ariadnegraphql.org/
Don't do GraphQL in C/C++.


> But the most important thing you get with GraphQL is batching.

Doesn't HTTP/2 make this mostly obsolete? One of its big features is request multiplexing.

Regarding the auto-generated code bit, are auto-generated GraphQL clients a thing? It seems like it would be doable, but I haven't found any (at least for the languages I'm using).


> Doesn't HTTP/2 make this mostly obsolete? One of its big features is request multiplexing.

HTTP/2 helps with the network layer, but your backend will still handle requests one-by-one. Depending on what you need to do, this might make a hell of a difference.

> Regarding the auto-generated code bit, are auto-generated GraphQL clients a thing? It seems like it would be doable, but I haven't found any (at least for the languages I'm using).

There's this:

    https://www.graphql-code-generator.com/
But yeah, on a second look I expected to find more. Anyway, having a standard way to do things instead of relying on one specific piece coupled to some language (swagger), it's certainly better. On the other hand REST APIs have a much longer history, so I guess it's normal for them to have more tools.


I believe by batching they mean operating on collections of entities instead of single ones. So you may have POST /pets to create a single pet from a json object, but what if you want to add a hundred pets at once? Even with multiplexing, this is often way less efficient. Often the solution is to have POST /pets/bulk which takes a list of objects.


I suppose it depends on the domain, but in all the APIs I've created bulk operations are fairly rare. I guess if you know upfront that your API would involve heavy bulk operations then seeking a tool that makes that more performant would be beneficial.


I use GraphQL (postgraphile) for my admin backend crud. This allowed me to do some incredible fast development with only minimal customisation (couple of PostgreSQL functions). Anything outside the happy path is handled by a REST API. Maybe we shouldn't think in absolutes, eg: only use GraphQL. For the same reasons I use an ORM, and raw queries where it matters most. The cliché holds true: use the right tool for the job.


Having spent several years working with GraphQL (using it in multiple projects and teaching it to others), I've found that in the majority of cases just doing a plain JSON-RPC API is preferable and far easier to reason about for all skill levels.

When I built Joystick [1], this is why I implemented the API system [2] as a JSON-RPC model, but stole the idea of validating inputs (optionally) and then on the client, optionally specifying tailored output (also optional—like how you can request specific fields back in GraphQL but instead of a custom query language, just pass an array of paths like ['customers.creditCard.expirationMonth', 'customers.creditCard.expirationYear'] for the specific data you want returned).

What I learned implementing that is that the typing/querying for specific fields ideas is brilliant, but much better when it's flexible (i.e., I want it sometimes but not all the time).

[1] https://github.com/cheatcode/joystick

[2] https://github.com/cheatcode/joystick#api-1


> It can save you bandwidth. Get what you ask for and no more

I feel like this a false truth.

Most people are building a web app, or a mobile app and consuming an api and displaying all the data they retrieve.

If you have an rest api which returns an object with 6 properties. And a graphQl scheme which returns those same 6 properties. You’re not saving anything.

Now if you have a website and a mobile app, where the mobile app needs 3 fields and the website needs 6 fields. You will obviously save on bandwidth with the mobile app.

The problem here is most of us are not building Facebook. The data saved is peanuts and the bandwidth cost is probably going to be far less than the total cost of doing the work to support graphql.

For a company like Facebook which has many different integrations as well as 3rd parties integrating, graphql is obviously a godsend as integrators and integrations can consume only what they require and save Facebook millions of dollars in bandwidth.


Every company I've worked for in the last 10 years had multiple apps across several platforms, each with many versions, all running in production at once. Even if you only care about the next version you are shipping and a handful in production that's a dozen variations.

In a REST paradigm you over fetch because not all of these variations need the same data, or you send less but then the clients thicker because they merge API calls and have divergent presentation logic, or you have a bajillion API versions.

There's often a lot of back and forth between the various teams for each rev of the API.

GraphQL lets the clients drive the definition of the data fetching. That's it.

95% of the criticism of GraphQL is people complaining that GraphQL doesn't solve the problem of preparing the API response for these different requests. While that's true, that's not what it's supposed to provide. Whether you have a REST API with 26 versions or a GraphQL API with 26 variations of query you're going to have to write a backend-for-frontend style service that resolves the results.

GraphQL just standardizes this process.


> 95% of the criticism of GraphQL is people complaining that GraphQL doesn't solve the problem of preparing the API response for these different requests.

This problem is solved by quite a few GraphQL providers nowadays. Hasura, DGraph (not true graphql but close enough), Prisma. I like Hasura quite a lot for many projects. Just define your database and you instantly have a full GQL API for the clients to use however they please, no backend required really. Doesn’t work for everything, but it’s pretty great for a wide swath of projects.


> If you have an rest api which returns an object with 6 properties. And a graphQl scheme which returns those same 6 properties. You’re not saving anything.

You aren't thinking big enough. We have a graphql API where we have a bunch of enterprise users all wanting to pull out different types of data. They can decide what they want to get, and pull exactly that data. They want access to different tables, fields, and for different purposes and with different filters. We don't have to be involved, we just give them the schema.


I guess it works, but it still seems like an extra step compared to giving them DB access unless they're in some weird place where they can learn to use GraphQL but not Sql/NoSql


The issue is we don't want them having direct db access. Aside from multitenency, permissions, and configuration issues (all solved by graphql) they could easily bring down a database instance (avoided via limits we impose via our server). If we didn't have multitenancy then it wouldn't be a problem.

But there's also the issue that some presentation and business logic is also provided by the graphql schema. Graphql knows which nodes connect, the db itself doesn't. And special cases like overrides, formatting, etc can be handled by the graphql server.


> We have a graphql API where we have a bunch of enterprise users all wanting to pull out different types of data.

That’s a great use for graphql. My issue is toooo many people are building web apps with graphql where they are the only consumer. They are not getting any of the benefits of graphql, especially bandwidth savings.

If you have many people integrating and you in vision the types of integrations needing very different queries for data then graphql is great.

But most companies are a website, maybe some mobile stuff, and not enough traffic to warrant the complexity or benefits of graphql.


> If you have an rest API which returns an object with 6 properties. And a graphQl scheme which returns those same 6 properties. You’re not saving anything.

Not entirely true, as it allows you schemas to scale, but your requests to remain small.

For example a "User" record might have 30 fields, and it might have more as the system evolves. But your requests that only specify "User First name" will remain the same size.


We're forgetting an elephant in the room. REST APIs make it easy to cache data. Do a GET /api/objects/123, and if the object hasn't changed since last time we'll hit the cache. You can't do that with GraphQL, because a URL doesn't descrive a single resource.

What I like doing is to create a REST layer that sits just on top of the database, and a GraphQL layer on top of it that allows all kind of fancy queries. Yes, HTTP is slow and multiple calls for a single request should be avoided if possible. But it's much easier to run server-to-server HTTP calls (especially if the servers live in the same DC or physical machine) than running client-to-server requests.



Some nits:

> It doesn't support map/tables/dictionaries. This is actually huge. I get that there might be

It does. You can define, say, an "any" or "json" type in your schema and emit anything you want at a field with such a type. For example https://stackoverflow.com/a/63588485

> No clear path for Api versioning

Some options include:

- Prefixes (`/v1/graphql`, `/v2/graphql`)

- Backward compatibility: only adding and not subtracting things you want to support.

Lots of fair criticisms though. My two cents:

There are very few cases for starting a GraphQL based project by writing a GraphQL server (resolvers, queries, etc). This is where devs waste time instead of exploring their concepts. Instead, use GraphQL with something like Hasura that generates the GraphQL service for you based on database schema.


> Instead, use GraphQL with something like Hasura that generates the GraphQL service for you based on database schema.

I generally disagree. While Hasura and the like can get you moving quickly, they let you cheat on designing your data model.

Ideally it’s a collaboration between all involved to develop a shared understanding of the domain, and the queries and mutations (how to read and write).

Where possible avoiding implementation details leaking into the schema will let you change those implementation details when needed.

If you auto-generate from a database, your database itself becomes your schema. This is rarely the best way to represent your data model in an API.


GraphQL is nice from a consumer's perspective but results in a lot of extra complexity on the backend IMO. It sounds nice in theory for the frontend to just request whatever it needs but there are often performance considerations that make this easier said than done. You end up either tailoring the database queries for particular GraphQL queries (i.e. eager loading certain things you know will be fetched) or implementing some sort of more generic dataloader pattern. The fields and data types become more explicit through the schema but there are still implicit access patterns in play. Definitely a tradeoff vs. a REST API where each endpoint can be highly optimized since you know exactly what's being returned.


It's not an unpopular opinion: it's true. Graphql is a terrible piece of software/paradigm.

I've completely avoided it for years. If a potential new job contacts me and they use graphql, it's an immediate no from me. It's an immediate red flag that the engineering culture at the company is poorly run and would be a nightmare to work in.

Run away, as fast as possible.


> It's an immediate red flag that the engineering culture at the company is poorly run and would be a nightmare to work in.

Well, at least I'm glad I know I'll never be working with you!

I'm not giving you shit because you don't like GraphQL, I'm giving you shit because of your asinine "if you use GraphQL your company is poorly run and a nightmare" comment.

Whenever I see a comment from any developer that says "If you use technology X then you are an idiot", then I know that developer is either incredibly junior and doesn't understand the tradeoffs in choosing any technology, or they're showing typical "if you don't like what I like than you don't know what you're doing" arrogance that inevitably always makes it a pain in the ass to work with that person.


Yep. I worked at a place that fired almost its entire programming staff because they insisted on using Visual C++ to build a CRUD app, while a team of contractors built a prototype in Visual Basic.

Needless to say, the VB app worked fine and became the product.


If you don't mind, would you explain this more? I don't understand the implications; VB does sound "worse" than Visual C++ for such a job, from an outsider perspective?


> VB does sound "worse" than Visual C++ for such a job

Huh? No no, on the contrary: Straightforward CRUD apps, that's exactly what VB was built for and excels at. Only Delphi is better.

The thing about "Visual" C++ is that it isn't (or at least wasn't, last I looked) really very visual at all. And that sucks for building simple in-house CRUD apps, where the VB / Delphi drag-and-drop UI builder paradigm is a huge productivity multiplier.


In C++ you have to manage your own memory. Why would you want to do that when you're simply pushing data around.

I wouldn't choose VB myself, but when it's between VB and C++ for simple data pushing, I would indeed choose VB.

Let's say it like this: if you need to move stuff, would you choose a F1 car or a minivan. I would pick the minivan.


No problem. At the time, Visual C++ lacked several important OCX controls that were included with VB, so they had to be hand-coded.

If you were building an application that does little more than populate forms with data from a database and then update the database, VB was totally adequate. The most important part of the job was the DB and query design.


Why is this “needless to say”, as if it should be apparent to anyone?


Because a CRUD app doesn't require any serious computing performance from the application, making C++ unnecessary. If another implementation won the race to functional completion, then... needless to say... it was the one to go with.

Today you'd probably just use browser-based UI.

Also if you've spent time in corporate development (rather than a software company), I think this scenario is a common one. If you show management a prototype that works, they're going to ask why we don't just make that the product. And if you don't have a good reason... you don't have a good reason.


I felt pretty confident about my conclusions of my first dusty old bank job that used a custom shittier homebrew of google web toolkit and no source control.


But that's very different. "No source control" means they aren't following or don't understand the very basics of software process management. That's very different from "If you use SCM system X, Y or Z you're an idiot."


Email and the windows file system is a SCM system if you're dumb enough.


You are right that this arrogant attitude is juvenile, but it is prevalent amongst humans in all areas. Unfortunately, there would be few developers to work with if you apply the policy of not working with arrogant, dogmatic developers.


Strongly disagree, primarily because when this type of attitude infects dev teams it is usually a cultural issue, not an individual one.

The primary, inviolable value I have, and look for, in dev teams is "strong opinions, loosely held". Meaning I want to work with engineers that have the experience, motivation and intelligence to have strong opinions about how things should be done, but it's also critically important that developers are humble enough to know other developers may have other experiences that can inform why a different decision can be better.

If you've worked in a dev team that embodies this attitude, you know how great it can be and how dev team members will naturally work to strongly defend the group dynamic that it fosters. Meaning if a developer with a bit too much arrogance joins the team, they can often be trained into not having to be so judgemental, or making disagreements about real issues and not emotional arguments ("GraphQL sucks and you're stupid if you use it") If not, the existing team will quickly reject that arrogant developer because they know how dangerous they can be to a healthy group dynamic.


> look for, in dev teams is "strong opinions, loosely held".

Rather strong opinions, not super-strongly held.

If you know you're somewhat flexible in your opinion, it's going to be quite strong, but not all that strong. OTOH, if you have an even somewhat strong opinion, it's no use letting yourself be swayed from it all that easily; make them advance quite a good argument for it first.

But then, depending on how heavily you load your adjectives, maybe that's what your (admittedly much more pithily put) version meant, too. I just wanted to put the modifiers out there lest someone read the maxim at its strongest.


I'm truly saddened to hear that this has been your experience throughout your career so far. It is not a universal experience. I hope you find a better managed shop soon that recognizes that it's easier to teach folks a tech stack than to teach someone to be a decent (or honest) person.

Too many tech shops sabotage their culture and dozens of potentially great contributors in order to keep a few (or one) toxic contributors that the powers that be erroneously believe are irreplaceable.

Anyone can be a 10x developer when you sabotage the well-being and productivity of those around you.


Well said. I would also add that it is perfectly fine to have a list of red flags, and it is perfect fine to define your own bondaries. Graphql is a red flag for me too, as well is React and node.js, and even git to some extend. I love simplicity when designing web apps, their backend, their frontend and the deployment process in between. Although the tech is old , I came up that vue3+pouchdb+quasar is an amazing combination for a stable replicable dev environment, pwa, supports offline usage, and introduces possible p2p replication between browser's pouchdb instances trough webrtc.

React , imo, is a good over engineered library suffering from fragmentation. Angular is less fragmented, and Vue is the most elegant, performant and versatile of the 3. Good Devs choose Vue after having worked with both react and angular. React Dev never tried Vue, nor Angular Dev try React. Vue Dev usually know all 3.

Having a red flag like graphql can tell a lot about technical overview and experience in failure.

Graphql solves a caching issue that Facebook has. Makes the frontend team life easy, making the backend team life hell , big big hello. Scope changes in the backend are terrible.

Unless your team is engineered driven, and engineers take tech decision, and setup the sprints, going graphql in the backend is a recipe for disaster.


This is like hating HTTP. GraphQL is a spec, not an implementation. GraphQL doesn't even mandate a network transport.

Solutions like Prisma, Hasura, and Postgraphile make GraphQL dead simple to implement compared to REST when exposing relational data.

AWS AppSync allows for a fully managed "serverless" experience as long as you're willing to do the schema creation grunt work and write Velocity templates. (FWIW, I'm not a fan, but it's still an option.)

Apollo (and Netflix DGS) are for when you're writing everything yourself, and you just need a simple API to tie in to the GraphQL spec in exchange for having to write/optimize/maintain it all.

The bright side to GraphQL is that you have choices, and when you present your "menu" of options, clients can grab what they need. Whereas on the REST side, any new requirements in calling requires direct interaction with the backend team and a new endpoint.

Honestly, server-based data access doesn't get any simpler than Postgraphile, but I totally see how you could get burned by an ill-fitting solution. However that is not GraphQL's fault. You might as well blame HTTP for problems you've had with Node/Express even though you've got other options in every programming language not to mention "pre-baked" solutions like Apache, Nginx, etc.

It's just a spec defining interaction, not a prescription for how that spec is implemented. It is also not a silver bullet. Right tool, right job, and all of that.


There’s this stereotype of a programmer, that while I think can be funny sometimes, still reflects a professional that doesn’t really exist anymore from my perspective.

Most software engineers I’ve worked with have been incredibly humble and dedicated. The mythical bearded guy that showers three times a day, comes to the office with shorts and flip flops, and refuses to install Windows on the accountant person’s machine because it’s objectively bad is something I’ve only seen in memes and stories from older people I’ve worked with.

I personally think dissolving this myth, along with the one that programming is easy and / or none of us know what we’re doing, should be a shared goal between people who care about what they do and how others perceive it. Otherwise we’re unknowingly cultivating it into existence, and I definitely don’t want to work with arrogant, dogmatic developers.


For me it signals maturity.

When it's a junior, I remember myself and think they still need to learn.

When it's a senior, I know it's not a senior.


> Graphql is a terrible piece of software/paradigm.

Says who, exactly? What data are you basing this on? Or is it a completely subjective opinion dictated by frustration likely caused by the lack of understanding of it?


Did you try reading the thread? What do you mean by data?

> Or is it a completely subjective opinion dictated by frustration likely caused by the lack of understanding of it?

You can ask this this very same question when people say graphql is an amazing piece of software/paradigm, except s/frustration/hype/


Your argument stops being valid the second you realize that a lot of devs who use GraphQL started out as skeptics (e.g. me), then spent time actually understanding its nuances before coming to a conclusion for a specific project/team.

And, in general, there's no such thing as a "good" or a "bad" technology, there are dimensions and each dimension is a spectrum: utility, adoption, availability, cost, complexity (although hard to determine), etc. to compress all that down to "hype" or "it sucks" just show how little time has been spent on understanding the nuances I mentioned above.

I don't claim GraphQL is amazing or even good, it just proved to be a great way to build APIs for the projects I worked on. I'm sure someone who builds firmwares for embedded automated plumbing systems would disagree (within that context). If you decide not to adopt it I just hope you do it after a rational, unbiased review of what the tech is capable of and what the shortcomings are, rather than "oh it's over hyped".

> Did you try reading the thread? What do you mean by data?

Please don't question whether someone read the thread or not (which is irrelevant within the scope of this discussion anyway) just because they disagree with you.


So you are sure that some tech that you avoided completely (and I assume have zero experience in) is a terrible piece of software.

Great. What is your take on the postal service structure of Turkmenistan btw?


Their service scope is waaaay too broad, no reason to be responsible for quasi banking services, traffic fine payment, and utility payment processing.


Services like those are part of the scope of quite a lot of national post institutions, and actually for quite valid reasons.


Based on your logic, you’ve never worked for Airbnb, Uber, Facebook, Twitter, etc… which is also funny cause they have fantastic engineering culture. What a strange way to filter yourself out of great engineering companies just because of a piece of technology


doesnt matter how beautiful the engineering culture/talented the pool if it works on ads/surveillance/facebook.


Yup, gotta trust the words from some unknown from internet, with 0 proof. As if we're all there, up in your head, able to hear every single thought you have and determine that what you say is pure, unfiltered truth.

If many manage to use GraphQL and be content with it, that should be an indicator to you. But, you chose it isn't and that you'll merely display how politely negative you can be.

Thank you.


> trust the words

> pure, unfiltered truth

noone is forcing anyone to believe in anything, it's just some guy expressing his strong opinions about a subject, but no, you act like someone uttered a blasphemy against the lord's name


It’s not an unpopular opinion on HackerNews.


You forgot number 1: '200 your graphql request succeeded, here are all your errors'.

...I get it, the gql request did succeed, I've previously described it as like a 'layer 8' on top of HTTP: the problem being that all the tooling is for HTTP.

I wish 'REST' was one thing - with generated OpenAPI servers/clients & 'links' for example we could achieve what gql sets out to, if only there was a single way to do it.


Your request could be fulfilled by multiple services, some of which may have errors.

Building on this are result types, where you can return a union with the intended type and something like AccessDenied for specific fields a user does have access to, but some other user might. Here you start to model the happy and unhappy paths of the data model.

GraphQL itself doesn’t really say anything about the network layer, it sits above that, in the application layer. You can run your queries and mutations over a websocket connection, at which point 200/4xx/5xx don’t make sense.


Like I said, I get it. (And fwiw '200/4xx/5xx' also sit in the application layer, just HTTP not GraphQL, which is why I described it as like a 'layer 8' (a fictional one above application) over HTTP.) It's just not a good 'DX'.


Our monitoring says all the requests are 200 OK, why is the client down?


> 200 your graphql request succeeded, here are all your errors

I'm not sure how that's a problem? The client knows where to look for errors: not in the http response code but in the JSON payload. Why is that an issue?


Yes, graphql does indeed suck. Or rather it is not the best solution for all client-server communication that people treat it as, so it ends up being used in a lot of situations where it does suck.

Backend to backend communication is almost never graphql (is that changing in a big way?) which would indicate the main reason for graphql in a client-server situation is data saving but at the cost of complexity and other downsides. Almost certainly the data savings in many cases is not worth it.

Oh and then you have things like Apollo having cache bugs that result in incident level problems.


Does Apollo really have cache bugs? Usually it’s the data itself which doesn’t have a unique id field, or the client hasn’t been configured to know about the proper id field.

Granted, it’s a problem to have to do that. But such is life with entity-level caching.


> It can save you bandwidth. Get what you ask for and no more

On the other hand, you tend to do "select * from FOO" and get more data from the db, because you don't know what the caller will ask for.

I don't think I've even seen a codebase filter the SQL based on the caller. I think I tried doing it once and it was a pita. (Please correct me if it's easy).


The typical approach that I've seen is to do "select * from FOO" for simple scalar fields that cost very little to retrieve from the database. If you have any fields that often contain large amounts of data, or any relations, you can provide a separate resolver for that field or relation, and then that resolver will only get invoked if the caller requested it. It's pretty straightforward, at least when using Apollo and TypeScript. (Obviously you would modify the original query to exclude such expensive fields so that you’re not duplicating work with the additional resolver.)

I still don't think I would personally recommend GraphQL to most companies.


"Very Senior Dev" here (though it amuses me to call myself that). I had managed to avoid GraphQL for a while, but recently had to actually look at it and use it. I was appalled that in this day and age, this hyped silver bullet basically requires me to build queries using strings.

I was honestly surprised by this: when I first heard about the idea behind GraphQL, I was certain that I'd pass in nested data structures.

I use it because I have to (external services jumped on the hype bandwagon), but I don't consider it significant progress. And this "save bandwidth" advantage is totally oversold, I really can't see how the savings can be significant in a practical way.


> I was appalled that in this day and age, this hyped silver bullet basically requires me to build queries using strings.

That's like saying SQL is crap because you need to build queries by hand. Conflating a protocol/spec with its implementation and/or the way it's used is not something a "very senior dev" should do (not questioning you personally, just the validity of what you wrote in this specific comment).

There are plenty of good GraphQL libraries that make writing queries/mutations and the whole schema a breeze. I've been using graphene for Python for a couple of years and, although it has some rough edges, it's actually pretty decent. And GraphQL is quite a good mental model to work with that both backend and frontend can share.

<rant>Honestly I'm getting tired of seeing these comments on HN, it's the same for Kubernetes or other technologies. Often written by someone who didn't take the time to actually study and understand the tech and use it for actual projects. Often with no data to back it up whatsoever. The quality of posts and comments here used to be a lot higher but it's slowly turning into a plaintext version of dev.to </rant>


The GP is right. GraphQL is especially annoying because it looks so close to JS/JSON, yet since no thought was put into how it might integrate into existing typed languages its actually surprisingly difficult to build a type-safe API around it.

And yes, SQL is "bad" because you write query strings. The funny bit is that GraphQL may be just as hard to model in a type-safe way as SQL is, if not a little harder. At least with SQL we have a reasonably good way to model it with methods (see LINQ). LINQ was built 15 years ago, so this problem was well understood back then.


> yet since no thought was put into how it might integrate into existing typed languages [...]

Says who?

> [...] its actually surprisingly difficult to build a type-safe API around it.

Again, says who? The consumers of the APIs I work on are mostly written in Typescript and constructing types based on the GraphQL schema is a completely automated process. Are you telling me that it's easier to build type safe APIs based on examples of what JSON each endpoint might output?

> And yes, SQL is "bad" because you write query strings

Ok then every single language is bad because every language's syntax is based on (conceptually) constructing strings. I don't get your point.


> Says who?

Says me, and also any other person that has tried to build a type-safe GraphQL query builder

> Consumers of the APIs I work on are mostly written in Typescript and constructing types based on the GraphQL schema is a completely automated process

Constructing "types" of what kind, and in what way? Types for queries? Do you need to rerun the tool every time you modify any of your queries? Does it need to watch your query strings to generate the right types for them?

> Ok then every single language is bad because every language's syntax is based on (conceptually) constructing strings. I don't get your point.

Instead of arguing, why not look at what LINQ does?

For the best experience, you should probably try them with an editor/compiler: https://github.com/dotnet/try-samples#basics


I'm not familiar with LINQ and even though it might be a good solution we're not debating GraphQL vs LINQ (which, as far as I can tell, is specific to C#, at least its reference implementation), I'm questioning your "string is bad" statement which, IMHO, doesn't make any sense.


It would be helpful if you actually explain how LINQ does it better.


LINQ lets you write SQL queries using the (.NET) language in which you write all your other code. This means you get to take full advantage of the language (and language service) features, including the typechecker, code completion etc.

Examples: https://www.c-sharpcorner.com/article/writing-complex-querie...

The hard bit here is making sure the language type-checker is fully aware of the involved types, both while writing the query as well as while selecting the results to be returned

This approach has since been copied in more capable languages. One of my favorite examples lately is Rust's Diesel: https://diesel.rs/ (see the "complex queries") example.

A query language designer aware of the above lessons learned with SQL might take special care to ensure their new query language is easier to model in existing languages. For example, they might consider an alternative OOP or FP based syntax, or to generalize they might put some thought into what would make it easy to write a type-safe query builder. After all, while SQL was developed in 197x and we had a different model for data access early on (stored procedures instead of flexible language-integrated queries) so its easier to understand that we didn't consider integration with other languags. TypeScript already did exist when GraphQL first appeared in 2015, and it's been 7 years of LINQ at that point.

Yet, we still went the stored procedures route. Tools such as graphql-codegen [1] require you to regenerate your types every time you edit your query strings

[1]: https://www.graphql-code-generator.com/


This is just a wrapper for SQL, every language has one. The same is true for GraphQL, I've never written a GraphQL scema or query by hand, always used a good wrapper that handled all the type safety I needed. Constructing GQL queries manually is the equivalent of doing it with SQL.

At this point I'm pretty sure you're conflating the underlying technology with what a wrapper could do on top of it. And in that regard I absolutely agree with you: raw GraphQL doesn't make any sense, the same way raw SQL (in 2022) doesn't make sense either.

EDIT (mandatory before I get lynched lol): except in cases where the wrapper builds a query that is inefficient or should be tweaked manually.


> I've never written a GraphQL scema or query by hand, always used a good wrapper

Could you give me an example of a good client wrapper that doesn't require you to write queries as strings?


Not sure if you consider it "good" but I've used this one quite successfully: https://ghostdogpr.github.io/caliban/docs/client.html#query-...


Its a reasonable looking wrapper. Could benefit from the ability to build queries with variables, although not sure if that would be useful in the Scala ecosystem.

To make it clear, I disagree I'm conflating things. I'm currently working on a TypeScript based graphql builder (https://typed-graphql-builder.spion.dev/) and I can think of several ways the language could've been designed to make it easier to write typed query builders.

This is not without consequences - since its quite hard to write the builder, most tools available for code generation (https://www.graphql-code-generator.com/) are built around editing GraphQL strings and will try to find them in your code and add type assertions. Additionally the rest of the ecosystem tools are built around supporting this workflow (graphql playgrund, etc)


> I can think of several ways the language could've been designed to make it easier to write typed query builders.

Would you like to share them? Have you tried submitting your suggestions to the GraphQL core team?


Even if I did share them, its too late for GraphQL to make that change - they are design decisions and people probably already rely on them

Here is a few:

- Less fine-grained field selection - allow for fields selected by default. This would remove some of the need for optionals in languages that aren't able to dynamically create record types on the fly

- Implicit unions and union queries are really annoying to model in both OOP and FP languages. In FP disjoint tagged unions with no inheritance would work better; in OOP common interfaces but no ability to define unions would work better. As it stands, the mix makes it difficult on both language types to support a general schema. Unions based on optional fields (like in GRPC) are probably best-of-both-worlds here.


Yeah, if you use something like Postgres and Hasura for a new project it's pretty simple. I doubt you could make a REST API much easier. Django + Django Admin is close, but that's not really an equivalent per se.


> That's like saying SQL is crap because you need to build queries by hand

If we want to use these terms, then SQL is indeed crap, because you need put query parameters in-band instead of out-of-band. This led to numerous exploits over the years, as it's difficult to ensure the data is correctly escaped. GraphQL just repeated the same mistakes.



Calling SQL crap just because there's a way to abuse it is like saying C is crap because I could do `int * userGuess = get_number_from_user(); * userGuess;` with nothing more than a compiler warning (if I'm lucky).

Would be nice if we all stopped with these blanket statements and just focused on evaluating individual pros/cons of things.

EDIT: formatting of pointer


> The quality of posts and comments here used to be a lot higher but it's slowly turning into a [..]

You can go on with your GraphQL, Kubernetes, gigantic frameworks, and pages with 3MB of JS if you want.

And let's see what stands the test of time.


Well, GraphQL aside I've been using the same stack for almost ten years and it's only becoming more and more popular so I'd say I'm doing pretty well in terms of choosing the tech, thanks for your concern though!


Agreed. I'm working on a typed query builder for GraphQL and TS but secretly I'm a little mad that nobody gave some thought to making it easier to integrate in a type-safe way at least in the client languages

https://github.com/typed-graphql-builder/typed-graphql-build...

No docs yet, that's WIP


It looks like a lot more boilerplate than normal GraphQL queries.


Not sure what you mean, I added the expected resulting GraphQL queries and they're about the same size. They aren't really normal queries, because I'm trying to exercise all of the features at once in the tests :)


Hmm, there’s really nothing preventing you from writing a library which allows you to pass a data skeleton to an async function and get a full body back.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: