Hacker News new | past | comments | ask | show | jobs | submit login
Migrating Netflix to GraphQL safely (netflixtechblog.com)
235 points by theptip on June 18, 2023 | hide | past | favorite | 218 comments



I never understood why people go for graphql.

In my experience, it's a nightmare to 1/ secure 2/ version 3/ ensure qos

Securing it properly should make it a no-go in like 95% of cases. you get amazing flexibility on the front end with a heavy heavy cost on the backend. Also, in general being able to say "i want to do whatever" and request everything at once is an anti-pattern IMHO, especially after HTTP2 became mainstream and doing multiple requests is reasonably fast.

Versioning? Forget about it. Now you have "all the versions" and good luck figuring out what is used, what is not used or god forbid deprecate something. you're going to have a bad time.

As far as qos goes, if any client can range from "i'm asking a simple thing" to "i would like the whole world please - and btw you're only going to figure things out as you pull them in" qos becomes a pipe dream.

Last, I don't understand what Netflix does that is so complex that would warrant something like gql. I just don't. To the naive developer in me it seems that they 1) need to have a basic api to get whatever catalog they have + a few apps build on top of that 2) have figured out how to do streaming exceptionally well in order to scale to all the people watching. That's is and although a gross oversimplification I cannot think about a scenario where gql is needed.

I think in their desire to reinvent the wheel Netflix has jumped the shark. A lot of really good ideas have come out of the innovation they did in the past but lately it seems like they are doing things for the sake of doing them or they are pissing people off with password household policies and whatnot.


Going to reply here because, as a huge fan of GraphQL, I strongly disagree with every single one of your points. To start, I think the biggest misconception I see about the value of GraphQL is people see it as some sort of generic "query language", which is unsurprising, given the name. If anything I think the biggest problem with GraphQL is that, if people just saw it is a simple alternative to REST, with a well defined set of query (GET) and mutation (PUT/POST/DELETE) endpoints, they wouldn't get caught up in all this "infinite object graph" stuff that I never hit in my day-to-day.

To your points:

1. I find GraphQL to be fantastic for security, primarily because all calls are strongly typed, so you can ensure by the time a request gets to your resolver it is guaranteed to match the defined input types. Furthermore, I always make heavy use of custom scalar types instead of String, which allows me to get rid of a whole host of potential security issues by limiting potential injection attacks before my code even sees it. As far as ensuring object ownership/permissions, this is trivially easy, or in any case just as easy as with REST.

2. Versioning is one of GraphQL's greatest strengths. The tooling makes it easy to deprecate some fields while adding replacement ones in a way that guarantees backwards compatibility. Far from "good luck figuring out what is used", the tooling e.g. in Apollo makes it very easy to see which clients are making use of which fields. Furthermore, if you do need to "hard version" a new endpoint, you can do it similarly to REST by including a version parameter in your URL (e.g. /v1/myGraphQLEndpoint).

3. Regarding qos, this again just gets to my original point about having well defined queries and mutations. Your queries don't need to say "allow me to see the world" any more than any other API framework. It's not hard to just have queries that only say "give me X by ID" and also a single bulk retrieval endpoint where you define the boundaries of what you want to return.

If anything, I think perhaps a lot of misconceptions around the problems of GraphQL have to do with these tools that basically say "expose my whole DB with GraphQL", which in my experience usually leads to tears in the end.

But starting with a thoughtful definition of your API surface area with GraphQL's type definition language can make it a joy to use and provides lots of benefits over a straight RESTful interface.


>If anything I think the biggest problem with GraphQL is that, if people just saw it is a simple alternative to REST, with a well defined set of query (GET) and mutation (PUT/POST/DELETE) endpoints, they wouldn't get caught up in all this "infinite object graph" stuff that I never hit in my day-to-day.

But isn't this "infinite object graph" like the only real valuable part of GraphQL? People get caught up on that because all the other things you mention aren't really an issue with normal REST API.

If you're saying you use GraphQL but don't use the key defining feature of GraphQL. Then what's the point of using GraphQL if you're just using a strict predefined set of things you can query/mutate?


Value of GraphQL imho is the ability for the api to be driven by frontend requirements without bothering the backend guys "to expose that one field in that one query".

Once the app is developed I think you might put up reasonable general limits to what queries are responded to in a general manner over the whole api.


This is how I have interpreted its value, and frontend devs have very plainly advocated for its use with this argument. I think this is a really silly value prop.

Behind the elegance of a query language that lets you get your perfect little payload, there is a complex server that could need to resolve and block on requests to multiple backends, touch different caches and databases, and do joins and sorts and projections. Front end devs will add the videoRating field and have no idea that this comes from a separate API and causes the response time to double.

Developing some gragantuan do-it-all meta API as a sandbox for frontend engineers is a terrible idea. You don't just slap a graph over your APIs and call it done. The GraphQL server is orders of magnitude more complex than a purpose-built API.

Ultimately once the FE devs have crafted their query to satisfaction it will hardly ever change. It's better to work together and decide whats needed and how to best get that data to your app.

I really favor collaboration on purpose built APIs than gargantuan do-it-all systems.


"Driven by frontend requirements" is how approximately all APIs in the world are developed. The problem GraphQL exposes, and makes extremely punishing when you ignore it, is that of poor communication of requirements.

Put it this way: you _could_ build a GraphQL resolver by means of mirroring your database schema or service structure, and let frontend engineers play in that sandbox while patching up holes. This would have the exact same result as building a REST API service that proxies requests to a SOA without understanding the performance or stability impact. Or the exact same result as exposing multiple REST services that must all be hit to render a single screen on the frontend, except you push the blocking to clients, which is not a proper solution if you care about the energy usage you don't pay for.

In all of these cases, the common thread is that the backend and frontend teams aren't working together and thinking of the entire product as a system instead of a frontend/backend split. GraphQL forces you to reason about the entire system and not a series of API calls, which can obviously cause problems with siloed teams.

This means I disagree with folks who attribute the power of GraphQL to "frontend-driven" APIs. Your frontend and backend is your product, so ultimately you must reckon with the boundary layer between the two.


This whole thread makes me happy that at my job we don’t have this arbitrary backend/frontend split. Everyone on my team does both—if you are working on a feature you implement all the parts needed for it. Seems like it avoids a lot of this coordination hassle.

Of course some people are better at one or the other so for very tricky things we might have them take over those pieces. But 99% of coding is fairly straightforward.


It's neither an arbitrary split, nor is the fact that everyone does both exempt you from this discussion. You are still concerned about this, unless you are doing some desktop app.


The thing is there are solid, replicable patterns for optimizing graphql. The way we use GraphQL is to expose "everything" to the frontend folks so they can work closely with design until they have a polished frontend for whatever they're building, then our backend folks look at it in APM in Datadog and figure out where to optimize it. Once we have an optimized query, we ship it. Everyone's aware of the basic optimization patterns we use, and backend is a pretty well-oiled machine.


> Ultimately once the FE devs have crafted their query to satisfaction it will hardly ever change

this makes the fallacy that it is FE devs driving change. it is not. it is product management. and to them (and indirectly to you), making it easy to make performant changes without 3 committee meetings is a Good Thing


This is a problem with siloing front end development, not graphql.


> Front end devs will add the videoRating field and have no idea that this comes from a separate API and causes the response time to double.

That's absolutely wonderful problem for the backend and db teams to detect and solve. Cache it, use another data structure, pre-calculate, build cunning indexes, if you can't do anything just throw hands in the air and say it cannot be done. Neither frontend team nor the client does care about backend woes. And frontend team doesn't want to be kept in the game of telephone as backend negotiates solutions for performance with the client.

That's what GraphQL does. Provides better separation of responsibilities between the teams and lowers the amount of conflicts and delays because of the reduction of verbal communication necessary.

> Developing some gragantuan do-it-all meta API as a sandbox for frontend engineers is a terrible idea.

It's not a sandbox for developers. It's for the clients. I know it's painful for the backend developers that front end doesn't want to be involved in challenges to the backend caused by customer's requests and how often they change. GraphQL makes those problems owned by backend devs and noone else.

> I really favor collaboration on purpose built APIs than gargantuan do-it-all systems.

Same as with the software itself, well separated parts, clear non-overlapping responsibilities, small, well defind interfaces between the parts result in better outcomes.


So you move the issue to the resolver instead? IMO graphql is trying to allow the frontend to be the 'driver', the first bit; otherwise you just have the backend publish an API and then that is what it is, if that one field is available from a different endpoint than the one you're currently using, that's the one you need to hit (as well), tough.

Not to say either way around is inherently better, I just see it as a switch from backend-driven to frontend-driven.

(Personally I'd love to use something like OpenAPI, with tooling more mature than probably exists, to be properly schema-driven, with both backend and frontend stubs/clients derived from that.)


> So you move the issue to the resolver instead?

Yes. Where it can be logged, inspected and dealt with wholesale.

It's moveing a problem from intra-team verbal communication into software where it can be dealt with more efficiently with software tools and methods.

> Not to say either way around is inherently better, I just see it as a switch from backend-driven to frontend-driven.

Yes. I think that's the whole point and main benefit of GraphQL which makes a lot of sense since apps that evolve through their development usually have most changes UI driven.


> Where it can be logged, inspected and dealt with wholesale.

Just as it could be in the backend? I don't follow that point.

> apps that evolve through their development usually have most changes UI driven.

That's a fair point certainly, but isn't completely generalisable - if you offer a third-party API at all (or think you might) then maybe don't special-case your own frontend.


> Just as it could be in the backend? I don't follow that point.

GraphQL server is the part of the backend.

The problem is that client has a new requirement, it is verbally communicated through UI change request. Frontend team implements the change then has to make a verbal request to the backend team for new data to be exposed. There's a bit of back and forth, testing. Everybody waits for everybody. It all takes time and is most of the time brainless busywork. GraphQL makes it so that request to the backend team doesn't need to be verbal (jira is same as verbal for me). It can be mediated through software and even fulfilled automatically if the GraphQL server is open enough during development. The cost of that streamlining is that at some point security or performance issues might arise, but those then can be dealt with solely by the backend and db team, as they should be because frontend is always insecure.

> if you offer a third-party API at all

For one such app 99 have both server and the client developed in sync.

And even then with offering third party api I think it's way easier to fall into the trap of special-casing your frontend with poorly designed REST than with GraphQL, althought there might be performance and security challenges as there always are with anything public. So there might be a bit to learn about how to deal with that in GraphQL ecosystem.


> It can be mediated through software and even fulfilled automatically if the GraphQL server is open enough during development.

You pretend that GraphQL is magic.

If there's requirement not exposed by the GraphQL server, the way to add it is literally exactly the same as for any other backend API.


Sure. But it's magic enough for me if I don't have to create a ticket for adding existing database field to a DTO every single time.


> But it's magic enough for me if I don't have to create a ticket for adding existing database field to a DTO every single time.

It means that those fields are already exposed to you by backend. Had they not been, no amount of magic on your side would make them appear.


So you've reached a point where working together collaboratively is such a burden that you've adopted technologies to circumvent that activity.

This suggests that GraphQL adoption is a sign of impending business stagnation. This does in fact align with my experience around GraphQL.


> So you've reached a point where working together collaboratively is such a burden that you've adopted technologies to circumvent that activity.

On braindead busywork, yes. Please automate everything about it as soon as possible, including communication. I don't want to collaborate on it with a human the same way I don't want to collaborate with a human on my McDonald's order and I prefer to access their ordering software through a kiosk or a phone.

> This suggests that GraphQL adoption is a sign of impending business stagnation. This does in fact align with my experience around GraphQL.

That very well might be. But stagnation understood as predictably churning an app after an app.


In my experience, braindead busywork is largely non-existent. Yes, there are times when you'll have to do something easy that conforms to code requirements and standards. But when the frontend needs to update something that is coming from a server, there is a real opportunity to discover, illuminate, and even solve architectural issues.

Sometimes that solution is to use GraphQL to make it easier to manage client implementation fan-out and requirement diversity. But GraphQL is never a substitute for communication and collaboration.


> In my experience, braindead busywork is largely non-existent.

Lucky you. In corporate environments I worked at it took easily half of the time.


So this completely contradicts your GP post who says the fact that it supports generic queries is not the point of GraphQL.

So which is it?


Generic during development. Once the dust settles you can restrict to what's used.


If you have 1, maybe 2 front ends then this is flat out laziness.

The front end arguement makes sense for someone like Facebook who has many different front ends and integrations. It’s unmaintainable to try do this any other way.


This is helpful, but it confirms my sense that a REST API with a typed spec like OpenAPI is going to get you basically all the benefits of GraphQL.


Pretty much, they are fundamentally both RPC flavors, so it's impossible for them to have different properties beyond more or less convenient tooling. It's always jarring to see those heated GraphQL vs REST APIs (as implemented in practice) vs gRPC discussions as if they are as different as, say, client-side CRDTs.


> Pretty much, they are fundamentally both RPC flavors, so it's impossible for them to have different properties beyond more or less convenient tooling.

REST arguably has better support for catching for read queries.


Pretty much except writing graphql schemas is actually quite enjoyable and expressive. I was always the biggest advocate for schema-first development, but OpenAPI specs were always such a pain to write and maintain. For this reason alone I would choose graphql (yet there are other benefits).


I agree, the schema language itself is very nice. The trick is to use a web server framework that generates the OpenAPI spec for you.


While taking half the time to do it.

I've yet to see one good reason to use GQL for anything but public facing APIs, like GitHub API.


If I'm understanding correctly, there is a lot more work a team has to do to build and maintain a GraphQL API and should only do it if they understand what they're getting into and what its advantages are. It's not for everyone, and everyone shouldn't assume it's for them.


> there is a lot more work a team has to do to build and maintain a GraphQL API

I wouldn't say that. It's simple and straightforward to get around some pitfalls of GraphQL, if you treat it as an enumerated set of RPC-style endpoints.

The commenter I was replying to stated "Thr fact that you're arguing that it should not be treated as a generic query language when it's in the name and this is how it's sold is hilaruous". Perhaps so. By far the biggest mistake I think the original designers of GraphQL made was putting "QL" in the name, as many people think it's in the same category of tools as SQL (I heard someone ask once on HN "Can you do joins in GraphQL?", which isn't even a question that makes sense). It should be treated as a competitor to OpenAPI, and there are reasons why I would prefer using GraphQL in many scenarios.

I think I'll probably write some longer form blog posts at some point about how I think GraphQL is easy to set up and get running quickly, and how to avoid some common misconceptions.


> By far the biggest mistake I think the original designers of GraphQL made was putting "QL" in the name

No. The biggest mistake why not emphasising to people the usecase they solved which was having many many different front end consumers and having to create many permutations of the same endpoints to cover web, mobile, various applications in different states, time to deliver endpoints to the teams. Etc

Most people are not working on the same number of implementations that Facebook or similar need. But they want to be on the bandwagon.


> It's simple and straightforward to get around some pitfalls of GraphQL

It isn't

> if you treat it as an enumerated set of RPC-style endpoints.

It's not that.

> I think the original designers of GraphQL made was putting "QL" in the name, as many people think it's in the same category of tools as SQL

"GraphQL is a query language for APIs" is literally the tagline at https://graphql.org/

And the frankly insane complexity of GraphQL comes from the fact that you now have to implement that query language, often over completely different sources of data.

Which leads to frankly inane solutions like the requirement to inspect the full request and the full response on the fly just to be able to cache responses.


This!

But I'll add one more: "Standardisation". Every RESTful API uses different URL paths, naming schemes, HTTP verbs, data structures, headers. Whereas those are defined by the GraphQL spec.

When consuming or creating a GraphQL API, those (usually meaningless) decisions are defined by the spec, so I only need to learn how the data is structured. Since it's a spec, my queries can be strongly typed in both frontend and backend.


I don't understand what you are saying here. RESTful APIs are supposed to follow a specific format, e.g. GET: candidate/{id}, GET: candidate, POST: candidate, body: CandidateDto, etc. How is GraphQL different? Keep in mind that you can "see what's available" on a Swagger page easily with a REST API.


For the security comment, I was thinking they were talking about authorization.

According to GraphQL, authorization belongs in the business logic layer[1]. A lot of projects ignore this advice and put it into the resolvers. This decentralized approach can be difficult to maintain and keep correct.

[1]: https://graphql.org/learn/authorization/


> if people just saw it is a simple alternative to REST, with a well defined set of query (GET) and mutation (PUT/POST/DELETE) endpoints, they wouldn't get caught up in all this "infinite object graph" stuff that I never hit in my day-to-day.

Can you explain this more? How can you avoid infinite graphs? If I have User {things: Thing[]} and Thing {owner: User}, you have to deal with this issue.


I have been writing GraphQL APIs on and off for the last 5 years, and in practice haven't had many scenarios where this was an issue.

In GraphQL the query for the example you gave could look like this

  ```gql
  query {
    user {
      things {
        owner {
          id
        }
      }
    }
  }
  ```
When resolving an array of type `Thing` for the `things` field, you would query for the user that the `owner` field represents. Rather than assuming all relations should be loaded for an owner by default, the client would specify the fields for the `owner` that it needs. Such as I have above for the owner id. Even if no fields are specified, it would be weird to assume all relations should be loaded by default.

Now if your developers are intentionally creating infinitely deep queries, then you'd solve this the same way you'd solve an infinite loop in your code today. An issue you would catch during development or CI/CD. This can be easy to catch using a linter or during review.

  ```gql
  query {
    user {
      things {
        owner {
          things {
            owner {
              things { } # etc
            }
          }
        }
      }
    }
  }
  ```
To simply protect from bad parties / developers, you might use something like https://github.com/slicknode/graphql-query-complexity

In addition you could introduce CI tools to enforce your devs stop writing such complex queries. Also see the @skip and @include directives that can further be used to control what data is queried. In practice, however, this isn't something that comes up too much. In cases where I have seen this happen, it's usually because a developer is trying to reuse fragments without considering what data they are querying, and whether they should be reusing those fragments.

https://graphql.org/learn/queries/#fragments


> In practice, however, this isn't something that comes up too much.

In practice this is an issue for any publicly exposed GraphQL API.

That's why the only solutions to the issue are to:

- either deserialize and deep inspect the query to try and figure out if it's too complex

- or to only expose persisted queries, turning it into a bad replica of JSON RPC.


Not sure it this is a great reply. Some valid concerns were raised, and in summary all you are saying is GraphQL is awesome because it has types, schema and defined queries / mutations. This is of-course the basics of GQL, there are a lot of complexities under the surface.

GraphQL does add some risks IMHO, e.g. client can send a really complex query (even a recursive one, e.g. get accounts for user, get user for each account). We cannot say this will not happen as we define the queries ourselves, since sometimes the API is exposed to clients which are not in our control. Queries can be sent which can almost bring a server down, so you need to handle that.

Also error reporting / handling is trickier as compared to REST (e.g. https://the-guild.dev/blog/graphql-error-handling-with-fp).


I think you misinterpreted the security aspect.

I assume what they meant (and what I mean when I talk about how dire security is on GraphQL) is visibility first and foremost. Which users have access to which data. Things like multi-tenant or even just “you have access to X-model or this specific field on this model”.

Couple that with inconsistent performance (at least for RDMS) and inability to make use of state stores in a sane way (IMHO) on the frontend makes it a non-starter.


[flagged]


> So in conclusion, you're moving the goalposts and asserting that everyone that has issues with the tech must be an idiot since it works for you.

That's not what GP asserted at all. You made some vague statements about gql, and they refuted with very concrete arguments.


I didn't call anyone else an idiot. You don't actually seem to be open to hear about how people can use GraphQL, in production, to solve a host of thorny issues that "plain REST" APIs commonly have to deal with. Congrats on your intellectual superiority.


> Falling back to arguing about typing show me that maybe you are not aware of the many interseting ways you can get screwed or maybe you just worked on simple straightforward things.

Please provide a few examples of this.


Since I'm not going to type a novel here is an example: https://wundergraph.com/blog/the_complete_graphql_security_g...

Also look at hackerone:

https://hackerone.com/hacktivity?querystring=graphql


Both REST and GraphQL API's can be well designed, or badly designed. While I'm a GraphQL fanboy, I would much prefer integrating with a well design REST API over a badly designed GraphQL API.

Having spent over 15 years integrating with, and writing API's, GraphQL was a breath of fresh air! If you think of GraphQL as a query language, you will find it frustrating. If you think of it like you do a REST API with all the ugly pain points straightened out and standardised, then it is a dream to work with.

GraphQL is as much of a query language as REST is. For example, most REST API's end up getting super long lists of parameters in their urls. How many eCommerce API's end up having REST URL's like:

/api/products?category=guitars&include_variants=true&page=20&per_page=100&exclude_fields=description,specs

Whereas, GraphQL transforms that into a simple, readable query, which does not require reading pages and pages of documentation to understand.

But, if you are creating well designed REST API's, I would prefer to use them over somebodies poorly written Graph.

Just like a REST API, a well written Graph should be crafted to be fast and performant to execute. Just like with REST, a Graph designer needs to sit down and think about the ways people will want to use the API. A good graph does not allow endless relationships that will cause performance to blow out.


/api/products?category=guitars&include_variants=true&page=20&per_page=100&exclude_fields=description,specs

Seems pretty readable to me.


Also, url query parameters are kind of orthogonal to REST vs. GQL.

They can complement either API. From personal experience, choosing not to use them (as most single page web apps don’t) can make testing painful and makes deep-linking to specific states of your webpage impossible.


> GraphQL is as much of a query language as REST is

This doesn't make any sense, unless it's to point out that GraphQL is not a query language at all.


> I never understood why people go for graphql.

It allows a full separation of the frontend dev velocity from the backend velocity.

The frontend is no longer dependant on backend engineers for API creation, nor negotiations on how those should look.

The backend can choose to observe the hot path of GraphQL and optimise those for your #3, but #1 and #2 don't differ from, say, REST.


So you're solving an organizational problem by using gql? Who needs proper authz/authn, security, scalability, sanity, qos if we can have frontend dev velocity? Checks out.


Solving organizational problems is a core component of any software you design in any organization that's not a 100% flat startup unfortunately.

> "Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure." - Melvin E. Conway

It's unavoidable. You can bury your head in the sand about it and demand that the technical structure only match your technical requirement, but then the organizational structure of the company will grind to a hault. People will always be people. Just because you give some of them a title like "Engineer" doesn't mean that we won't conflict on people problems.

Entire concepts like event driven architectures or microservices, while might have plethora of technical pros/cons are mainly pushed by management for their non-technical aspects. One of their main non-technical pro is organizational. If your component just emits events, handles events, and is implemented as a separate microservice then you can always just insert a team, or move a team in an organizational structure while minimizing the overall impact to a project.


> So you're solving an organizational problem by using gql?

Yes, of course! All problems are organizational problems at scale. I have no great love for gql, but painting it as a black and white decision pitting FE velocity against all other engineering concerns (including hyperbole like "sanity") is childish. There are legit tradeoffs discussions to be had, but if you think it's impossible to secure or scale gql then you're not a very imaginative or resourceful engineer.


Don't we solve organizational problems with software all the time?

Git Monorepo vs Polyrepo Microservices vs Monolith Kubernetes


Reminds me of Conway's Law, which states that the structure of your systems will mirror the structure of your organization.

https://en.wikipedia.org/wiki/Conway%27s_law


See also: Reverse Conway.


The simplest way to add auth is to read a user session and provide it in the context, and then do the logic in the resolver for access control. It's not any different from how you would do it in a regular REST based server and GraphQL certainly doesn't do anything specific to get in your way about it. Not sure why people keep bringing auth and scalability into it. Clearly facebook invented and uses it for the purpose of auth and scalability.


GraphQL really needs a gateway like Envoy to give better observability / control / auth, and indeed that’s how lots of people deploy it.


Okay. Tell me how you do the control/auth and allow certain users to access a resource while others do not access it while they may formulate complex queries where they ask for the kitchen sink.


By wrapping the code that loads data with code that checks whether the current (i.e. requesting) user is allowed to load that data. I don't really understand the problem, how is this any more difficult than any other API paradigm?


I think the additional issues come when you want to define access by a relationship instead of just the entity, which means you need to check access based on the edges, and not the nodes. You'd have to do this anyway with REST, but I think it's easier in some ways to make mistakes and allow more access than intended.


I honestly don't understand the complaints here. In our deployment it's implemented as an HTTP handler right next to all the REST ones and gets all of the standard authz/authn/obervability wrappers. It's allowed us to focus more on core development because the schema was exported over a year ago and hasn't changed much. It functions almost identically to the REST components but is easier to develop against. No issues with scale or performance that aren't apparent in the REST components either.


> Tell me how you do the control/auth and allow certain users to access a resource while others

how would you do this with REST? or any other kind of API? graphql, at it's core, is a tool for the frontend to describe to the backend what data it wants. how the backend replies to that is completely up to the backend.

> formulate complex queries where they ask for the kitchen sink

most concrete implementations i've seen include a way to limit complexity. in `graphql-ruby` for example, you can limit how many nodes, and you can apply a "cost" to a particularly expensive-to-calculate node if you like. Say you give an API only 10 "complexity points". You could make most nodes cost 1 point, and expensive nodes cost 3 points. Now, someone can _request_ the kitchen sink, but you can respond with a "no".


https://konghq.com/blog/engineering/graphql-authorization-at... has a pretty comprehensive look into one way to handle auth with Kong. I believe Envoy can do something similar. It’s not as easy as an htaccess with regex on routes but it’s not impossible.


This is handled at the library level, typically. For example in graphql-ruby, it’s built in [1]

[1] https://graphql-ruby.org/authorization/visibility.html


Honestly there’s a few good ways to do that. Schema directives, regular old permission system at the resolver level, etc.

I’m not a big fan of GraphQL, but I it’s not particularly difficult to secure.


Is it not possible without Envoy? IMO this feels like a failing if I'm relying on a separate piece of software. I'm comparing it with RESTish services which are easily scaleable in many ways either software or infra. But that might be my misunderstanding of what you just said


It’s something that’s handled a lot these days at BigCos by service / query gateways / proxies and in the places that utilize these heavily it’s pretty automated from my experience. Basically the dev experience is you go into some web ui or make a PR against some JSON / yaml policy to allow whatever then it just works because some other sec / infra team plumed in all the auth and access control parts.

GQL itself doesn’t attempt to solve authZ or authN by design.

Edit: if you want to do this with nginx or within graphql / express, this is what that could look like https://www.apollographql.com/blog/backend/auth/a-guide-to-a...


> frontend is no longer dependant on backend engineers for API creation

So long as the backend engineers at least anticipated all the relationships, properties and objects that the frontend might ever need?


What? And who is writing and implementing the GraphQL schema??

I work on a GraphQL backend and I can tell you, every time the UI needs some new fields we don't have in the GraphQL schema, I've gotta go and implement that just like in REST, the fields don't magically materialize into existence.


Except when it’s not performant, and then suddenly you need those backend guys again!


If GraphQL is set up correctly ie through Apollo Server or other server implementations which implement performance optimizations, backend people will never have to touch it again, yes.


“No true Scotsman” fallacy surely? Yes, in theory, but in practice, all sorts of issues like the N+1 problem can pop up


In Apollo server you can add directives to your scehma for authz. It's dead simple.

I'm surprised how so many HN posts about graphql just slander it. If you go to the website and look at the use case of why it was made, it makes it pretty clear when it could be a good to use. My experience with it has been very straight forward and a joy


For me it was the prevalence of GraphQL that was annoying. I have worked with it and liked it as a technology, but it was a tell from the org I worked for an was definitely overkill for what we were doing. No matter how you slice it, GraphQL is added complexity compared to REST but of course, as with a lot in our industry, there are all the people bought in who put in the time to learn it who are going to shout, "Naw, it's easy!" To be clear I'm not saying GraphQL is super complex, just more complex than REST and if all you need is REST then that is what you should be using. Yet in my many interviews over the past year I talked to a bunch of companies who used GraphQL and I'd say, "Oh, cool, why did you choose it?" and they'd say something along the lines of, "Well, the CTO who wrote the original app thought it was cool at the time." So I've always got the impression that the backlash mostly comes from the huge evangelism it got making it out to be The New Way. Again, to be clear, I'm not saying it was marketed this way but it's how it felt at the time. Annnd again, I know this happens constantly in our field.


GraphQL (as in the language spec) offers no way to perform authz. Just because there are non-standardized extensions out there for some languages, doesn't mean it is available in whatever language you're using.


Ok, but that’s true whether or not you use GQL.


Sure. I could respond with a 4xx code because you’re not authorized for that field. Ah, but maybe you want to know which field? Too bad GQL doesn’t really support that.


GraphQL has strongly typed errors unlike REST. It is very akin to the Result type in many languages in that you are forced to handle errors even when writing the query, and the query will simply not compile if you don't.

For example, the Pothos library implements this pattern automatically:

    type Error {
      message: String!
    }
    
    type Query {
      hello(name: String!): QueryHelloResult
    }
    
    union QueryHelloResult = Error | QueryHelloSuccess
    
    type QueryHelloSuccess {
      data: String!
    }
    
This field can be queried using fragments like:

    query {
      hello(name: "World") {
        __typename
        ... on Error {
          message
        }
        ... on QueryHelloSuccess {
          data
        }
      }
    } 

https://pothos-graphql.dev/docs/plugins/errors


But now I’m most likely returning a 2xx response. There are asshole corporate middle boxes somewhere that will cache it. If I return a 4xx response, from experience (albeit nearly 5 years ago) I’ll crash your client. Now what?

If someone has solved the asshole corporate middle box problem using GQL, that’s really good news.


Authorization errors can go in the errors array which has a path reference in the standard.

You generally don't want to use HTTP error codes with field level errors in GQL.


So still a 200? Or a 202, 206, 207?


401 or 403. Why is this a question?


Because there may be fields requested correctly alongside some requested incorrectly


Outside of very few cases it means the request was incorrect.

And bo one is stopping you from returning a response that contains error details.


[flagged]


My SaaS backend is a GraphQL Server that has single-handedly saved me tons of hours for integrations and coding. The first iteration of the app was using rest and that was a pain. Hitting multiple endpoints to get all the details of an order is not something I miss. On top of that, I get a beautiful playground that acts as a query builder and documentation.

Have you actually used GraphQL in production or for a wide-scale project? A lot of these criticisms for GraphQL comes from people who have played with it for an hour and determined it's not good. Give it a real chance and you'll see why big companies are using it and understand why the ecosystem is growing so fast.


Yes. Used it for a a couple of large projects at BigCo. Was actually brought in to "polish" a few things. One of the original team members thought it was cool. It was a disaster. Uncovered issue after issue. Convinced management to run a bug bounty program through hackerone and I'm going to let you guess what happened.

If you're so brave and confident find a good pen tester and let them have a go at your api. It's a humbling experience.



I hate integrating with public GraphQL APIs as well. Give me a REST API pls for the love of god. It makes me sad GitHub's new projects API is GraphQL-Only.


Netflix is large company with huge IT/software workforce. And as I have seem in large companies tech managers and engineers don't usually keep waiting for actual problem to appear and develop solution for it. They are going to take initiative to migrate legacy monolith to next generation micro services, GraphQL architecture and in process save their jobs.


The timing of this is hilarious. Here is something that's on the front page at the same time: https://news.ycombinator.com/item?id=36380711


Thanks. Great read.

When work or personal issues overwhelm me I go with this kind of meta analysis and stop usually at Keynes quote : In the long run we are all dead. This helps me get though the day.


Have you tried the alternatives? We went with Odata, and it's hell. It's fine on the client side, but it's terrible to work with on the server-side. We went down the C# path because everyone else is either using RPC or GraphQL, but even Microsofts own libaries don't work together. The model creatirs for Odata and Entity Framework sort of work the same, but are also different enough to cause some real annoyances and once you add asp.versioning it becomes even worse. We went with Odata because we had a hefty client that consumed Odata through a client library that we build ourselves, and at the time it seemed like it would be fine. A year later it turns out that it would've been better for us to rewrite everything to work with GraphQL, and, we may actually end up doing that eventually because the Odata .NET support is so terrible that we're constantly having to rewrite parts of it to get it do things that are trivial in GraphQL.

You can of course go other routes, we took a serius look at tRPC, but it seemed like it would end up being a lot of work. Actually quite similar to how doing the things you want from a frontend perspective is a lot of work if your backend is "just" rest.

> Last, I don't understand what Netflix does that is so complex that would warrant something like gql. I just don't.

If you dig into the other blog points that the OP link to you can see that it's because they needed better performance, more security and better control of the flow. I think you may underestimate how much you get for "free" when using graphQL. It has so much adoption, that there are so many tools that you won't have to build from scracth, even if you're Netflix. You can see our Odata library as an example of this, there are client libraries that we could've used, but they're bad. So we had to build our own. With GraphQL we wouldn't need to do that.


IMHO, Rest works just fine. If you are serious about performance I don't really get how you do that with GQL. maybe I'm just ignorant but the apps I've worked on were medium to large size and it was a fricking nightmare (apollo-based, a couple of years back).

Here:

https://hackerone.com/hacktivity?querystring=graphql&filter=...


> maybe I'm just ignorant

Never that, but maybe inexperienced? Nothing you say is wrong, but you need to look at it from the organizational point of view. The way we build (most, all of them where I work, but I'm sure people can point to places) "enterprise" apps today, is that we have a frontend that's build in Typescript, and then something behind it to move the data.

Your frontend engineers are going to want a query language that allows them to pick and chose the data they need. You can do that with rest, but you really, really, don't want to build it yourself. Some frameworks have options for parts of it, but in general you're out of luck when it comes to things like inheritance trees on objects. So you have Odata, RPC, GraphQL, and while Odata is nice on the client side, it's not nice on the server side. RPC's work great, but they are also a lot of work, and then you have GraphQL. What GraphQL allows you to do is the combination of having an engine that makes your frontend engineers happy, while allowing your backend engineers a lot of visibility on resource drains. This means that you can work on the heavy load areas, and "leave" the others, more easily than you can with Rest where you're likely going to "over engineer" a lot of your backend. RPC is sort of like Rest in that department, but because it's intended to be like that, its rarely an issue because you chose it for that reason.

Or to put it more simply. You use Odata and GraphQL and not Rest because they lessen the "working together" burden.


I think it's simple. You can get the best performance with REST, but you have to really put lots of resources into it.

On the other hand, with constraint resources, you likely end up with better performance when using graphql because of the reduction of requests and decreased latency.

In most cases, graphql hits the sweet spot.


> reduction of requests and decreased latency.

How?

GQL still depends on an API or a database, isn’t it? And depending on where that Api or DB is located in relation to the calling user/app latency is still going to be the same? What am I missing here?

If you are implying that GQL somehow intelligently caches data, then all the issues with cache invalidation etc still would apply, correct?

The problem with some of these debates about GQL vs Rest us that you have people either saying GQL is great or bad and same with REST. I wish there is someone that breaks it down and truly explains the pros and cons of each.


You are right, but you are missing the frontend part.

e.g. frontend says "backend, give me the users". Then later, for every user it says "backend, given me the users favourite images". However, with graphql the frontend can say "backend, give me the users and include each favourites images".

Even if the way to retrieve it from the database is the same for the backend, there is still reduced latency because it is only

frontend->backend->db (users)->backend->db (images)->backend->frontend

instead of

frontend->backend->db (users)->backend->frontend->backend->db (images)->backend->frontend


I think that it might be because the difference is mostly in how we work together. With GQL your frontend and backend engineers are always happy, with Rest they are always at each others throats to deliver. This is because GQL gives your teams the tools they want. On the frontend you get the data access without ever having to talk with your backend, on the backend you get the load data without ever having to talk with your frontend. So both your frontend and your backend can focus on what they do best without ever talking with eachother.

Obviously that's not exactly how it works, but if you give your frontend engineers the full query abilities of GQL and your backend the ability to monitor and then fix bottlenecks through the GQL load tools you simply remove a lot of the conflict zones in modern development.

You can do everything you can with GQL with Rest, but you're not going to want to do it. And speaking from experience, you're not going to want to do it with Odata either unless Microsoft magically improves the experience after 10 years of it sucking.


GraphQL is such complete and utter garbage for anything but the simplest of queries. I pity anyone who has to use it for anything more complicated.


i would not go as far as saying complete and utter garbage, but it 95% of cases it brings with it a can of worms that you don't need and don't want. All in the name of "frontend developer velocity"!


This rhetoric pops up every time gql is discussed on HN, and it is invariably full of misconceptions and, well, nonsense, that just tells anyone who's actually used gql that you clearly haven't.

I never understood why people insist on having strong opinions on things they clearly know nothing about.


For us the primary value is behind the customizability of it all. One of our main requirements is to give user A LOT of flexibility to customize the default frontend to suit their needs.

On top of that we are running DDD in the backend with ARs being spread over multiple different services.

We did experiment with rest early on, but we found out that we would need to make our frontned to be extremely complicated and vocal to handle the customization/data fetching requirements or build our own REST gateway on top of open API, doing, essentially, the same thing that graphql gateway does out of the box.

Adopting graphql was scary at first with low team exposure to the technology, but using REST would have made our life much much harder


My main issue with it is client-side caching doesn't map cleanly to graphql. I want well-defined objects to cache.


that's solved with Relay's graphstore


There's a solution to everything /s We started with a somewhat simple problem and now let's keep throwing things in. How about something I can just curl? Is that too much to ask?


Well, no, Relay is how GraphQL is meant to be used and is Facebook's client implementation and quite opinionated. Apollo and others came around to be less opinionated (and thus allowed people to re-use their old REST style designs) in GraphQL.

You can in fact just curl a GraphQL API. In simple projects where I don't need caching I just use the REST library and make a simple HTTP request with a graphql query string. I get back a JSON object to consume.


GraphQL is like SQL. It’s an extremely leaky abstraction but in the hands of someone experienced, you can do amazing things with a fraction of the effort required.

But just like SQL, you have people who happened to learn SQL in passing and it’s like a table saw in the hands of someone who doesn’t know what to do.


Kong seems to have some offerings on the API gateway security front for GraphQL https://konghq.com/blog/engineering/graphql-authorization-at... I haven't looked at it very closely yet, but I'm wondering Kong for other reasons (unrelated to GQL)


GraphQL really shines when it comes to providing a unified data layer for frontend teams. Having a consistent, typed API is a big time saver for developers building data rich applications. The ability for frontend teams to shape the data they need without talking to a backend developer and reduce the number of requests made to the API makes for a perfect match when building high performance applications.


> Also, in general being able to say "i want to do whatever" and request everything at once is an anti-pattern IMHO, especially after HTTP2 became mainstream and doing multiple requests is reasonably fast.

It's not about performance, it's about being able to trivially get the data you need in one request and get it back in a way that you've structured.


People are drawn like moths to a flame to anything that is poorly specified and are repelled by the well-defined. A visit to the ontologist is feared somewhere between a visit to the oncologist and the orthodontist.

To be fair, GraphQL has a real specification now but it didn’t back when it was taking off like wildfire.


The state of the art of GraphQL tooling around securing and versioning has evolved significantly. You may want to take another look at what’s out there.


I was just researching graphql versioning and the recommendation is not to version because the graph is supposed to be an evolving entity.


mutation createUser-v2

Seen that in some productive APIs, always fun.


[flagged]


Put this into the "my code is self-documenting" bin.


my self-documenting code is evolving!


Could you please provide some pointers?


How does http2 skip the speed of light to speed up sequential requests?

Isn't the back and forth across the network the big problem?


In the beforefore time, you would need to establish a connection for every request you did if you wanted to make multiple requests in parallel and you were limited by how many request yoi could have in flight in parallel. With http2 you can mux the requests together through the same pipe. Yes, if you need to retrieve A to figure out you need B, it's not going to be "faster" but you would do the same thing on the server side.

Also, for a well architected backend you can spread load better on the backend and shockingly you can also leverage caching if you are doing a "dumb" rest api.


GraphQL makes it straightforward to do conditional queries like:

  … on Book {
    title
    author
    if_viewer_can_purchase {
      price
      shipping
    }
  }
This is quite annoying to do with traditional REST without overfetching data you don’t need.


I feel like this is a bad take: I’m not sure what your experience with graphql is but your comments about Netflix strike me as naive. I think there is a simplified version of Netflix that doesn’t do eg recommendation or history or different contracts in different countries and so on, which is maybe just a few api calls, but I don’t think that’s what Netflix is. And are they actually reinventing the wheel here? I thought graphql was a Facebook thing. Maybe you meant to say that they are rewriting systems pointlessly but it (also) feels like a bit of a generic criticism that is easy to apply to companies for which in-house systems make sense.

(Edit: it’s not even like this is a graphql vs rest change as Netflix have had graphql for years and they have a custom api system that seems a lot more like graphql than it does rest)

I’m curious what you think the best advantages of graphql are, particularly for a larger company like Netflix?

I would guess:

- reduces coordination/contention between different frontend/backend teams (eg there are many clients – desktop, mobile, various smart devices – but maybe other front ends too like something customer support might use).

- cuts down on ‘boilerplate’ api work. For example, maybe you have some property X of each item Y in your catalog, but which you don’t get on the request for the catalog, and that you want to display this now (maybe it’s some new experimental feature you need to thread through from some database table to the front end). You need to choose between adding X to the catalog (potential version woes…) or managing a bunch of requests for X for each Y (risks being slow or bad in a few ways), or add some non-restful api endpoint that takes a list of Ys and gives you their X properties. With graphql you need to teach the backend how to get X of Y but the frontend only needs to change the query.

- it potentially lets you apply access controls in a more straightforward way. If someone is from the US, maybe there are some shows they can’t see. In that case we probably want to hide all records in results about shows they can’t see. (Alternative example: various properties of other people’s accounts). If you have many separate api endpoints, it feels easier to me to accidentally screw up on one of them.

I’m not really very familiar with graphql but the middle option is the most compelling one for some of the things I work on (which are nothing like Netflix). One assumes that some people from Netflix had reasons for graphql and I’m interested in what they were rather than some imagined Venn diagram with the current api in the ‘not invented here’ area and graphql in the intersection of ‘invented here’ and ‘not yet a thing we have’. I’d also be curious to see how well it works out for them over time – perhaps they’ll regret it but maybe not for the reasons you oppose graphql; if there are organisational problems (like some team becoming a big new bottleneck or some teams being unhappy about it being ‘forced on them’), they can be hard to write about.


The comment about Netflix was suppposed to be a hyperbole.

I would be curious how Netflix itself justifies this except for: we wanted to do this cool thing, so why the fuck not


Netflix might be a good example of where GraphQL is good: There's not one frontend, and one working app, but many, just by hardware platforms they support. Add to that changes in behavior for different regulators, licensing agreements and such, and I bet there's a bunch of bespoke little frontend things that need slightly different information from each other. In that environment, queries aren't really completely free flow, which is what could ge you in trouble, but it might be nice to provide cheap customization of the API, instead of building bespoke backend tweaks for every one of those bespoke frontends.

It's ultimately not unlike how people wonder why the Uber app is so big, when everything seems so simple to them: Each interaction appears simple, but put all the interactions from every person together, and the problem is far harder than it seems.


It's 2023. There are _so many tools and patterns now_.


Why? What problem did this solve for them? I use Netflix a lot, and I use it on AppleTV where I get automatic updates to the device and the app... the app has never changed except to get slower over the years (and I mean a lot slower). There is absolutely no new functionality they have ever deployed... isn't the app "done"? Is there some serious scaling issue on their backend that is causing the perceived frontend slowness that this will fix? Is this going to massively decrease the costs of the backend? Or is it just that the engineers are all bored and can't accept the idea that the product is either 1) done or 2) needs a new direction (instead of some new tech)?


> isn't the app "done"?

Netflix is an ecosystem, not just the frontend app for Apple TV. Netflix is pretty close to a vertical monopoly for some of its content. Fund-raising, planning, development, post-production, translations/dubbing, preparation for distribution, and distribution. Your idea of viewing a video content on the app is only the last 20%.

Also worth reminding people that the AppleTV app is not the only app Netflix supports for viewing. There have been dozens/hundreds of different apps and most are still actively supported.

Also, they are a company, so they are always looking to be able to optimize and cut costs.

It’s worth staying curious and asking why before assuming you know more than the engineers who have to work “behind the curtain”.


How would vertical integration be related to migrating the iOS and Android apps to using GraphQL?


Scroll to 7:47 in this presentation[1] and see that the different domains within the Netflix vertical are all part of the same large API, accessible from the same API gateway.

People here are making an assumption that the entrypoint to Netflix's microservice ecosystem is only for the "TV App". No -- their other domains (incl. talent and production) also depend on the same API gateway. When they upgrade the API gateway to GraphQL for one app and you might as well do it for all apps to get the benefits of the GraphQL toolset.

[1] https://www.infoq.com/presentations/netflix-scaling-graphql/


If their dev team believes there is value in GraphQL, maybe they also want those same benefits for their business apps/APIs in addition to their customer-facing ones. Maybe they all use the same API gateway.


I’m no expert, but as I understand it, the clients have more flexibility to request things from the backend. I don’t know the app source code, but maybe it reduces complexity in app design?

Would love to hear other opinions.


> Fund-raising, planning, development, post-production, translations/dubbing, preparation for distribution, and distribution. Your idea of viewing a video content on the app is only the last 20%.

Ok, so you are saying this GraphQL API is also being used by numerous integrations behind the scenes that are--in your estimation, as I find this idea pretty awkward--managing the fund-raising, planning, development, post-production, etc. of the numerous random production houses that are working on projects for Netflix all somehow within Netflix's central database?

> Also worth reminding people that the AppleTV app is not the only app Netflix supports for viewing. There have been dozens/hundreds of different apps and most are still actively supported.

Is the claim here that one of these applications on other platforms has new functionality that isn't available on any of the major ones? I mean, I listed AppleTV as I can guarantee the app is both not changing and getting slower, but it isn't like I am not using Netflix on other platforms and it isn't as if I don't know it is also embedded into a ton of random one-off devices... I just don't see what point you are trying to make by expanding the scope here as it feels a bit like an attempt to nitpick rather than educate how I might be wrong here.

> Also, they are a company, so they are always looking to be able to optimize and cut costs.

I suggested this as an option in my comment. Do you believe this cuts costs? It wasn't at all clear to me that doing all of this work would cut costs, but if you can explain how that would be fascinating. (It, though, sounds like you don't know anything more about this than I do: you are just less skeptical for some reason. If you work for Netflix and would like to publish an article about why this update was a great idea I would totally be the first to read it and applaud the effort, though.)

> It’s worth staying curious and asking why before assuming you know more than the engineers who have to work “behind the curtain”.

You are literally responding to a comment that begins with "Why?" --one which then continues with a ton of questions that could simply be answered by someone at Netflix if they so cared (and frankly, I will claim, should have been answered in this blog post, as the subject matter begs this question and usually one starts a project postmortem with a comprehensive section on one's motivations)--with a comment trying to establish the moral high ground by... saying I should ask why?


Some of your questions are answered here:

https://www.infoq.com/presentations/netflix-scaling-graphql


It replaced Falcor [1] which was extremely similar to GraphQL but also entirely incompatible, and was owned and maintained almost solely by Netflix staff, with GraphQL which has a large community of developers and users. Released to the public at nearly the same time, after several years in the hands of open source communities the verdict seemed to be: Falcor lost, GraphQL won. In theory this saves Netflix continuing maintenance costs of Falcor (which it can now entirely deprecate/stop work on, though there is no current warning in the repo other than maybe a comment in Issue #1016 [2]), and instead externalize more overall maintenance work to the much larger GraphQL community (including teams like Apollo and at Meta).

[1] https://github.com/Netflix/falcor

[2] https://github.com/Netflix/falcor/issues/1016#issuecomment-1...


Nice, open source propping up a big tech firm with absolutely zero benefits except a few highly opinionated pull requests


I have definitely noticed and been frustrated by what you're calling out here. There always has to be something to work on, even if that thing might invalidate a significant amount of previous effort or cause regression. As a developer myself, I guess it is good for me, because it means job security. And maybe that's why there's always something to be added or changed or re-created on the products I've helped develop - to ensure all the individual contributors have something to keep them busy. But it definitely is frustrating that it seems like an app being called "done" is extremely rare nowadays. Though I suppose developers didn't really have the choice to continue development indefinitely back before the internet allowed "miscellaneous bug fixes and feature updates" patches to be pushed weekly.

Edit: I just noticed who I was replying to. Thanks for your work on Cydia and in the iOS jailbraking scene at large. I have lots of fond memories jailbraking and installing all kinds of weird tweaks on my iPhone 4 back in the day.


I’ve often wondered this as well. It seems like the amount of client core data is really small, like fit into a single payload small, and changes very infrequently (a small subset maybe a few times on a busy day).

Are custom listings/ordering the blocking issue that takes several seconds to load when the app starts? There’s so much amazing low level work that I’ve read from the Netflix streaming team, but the front end has always seemed lacking (why can’t I easily just get a list of all the videos)? It effects how I use the app?


> why can’t I easily just get a list of all the videos

Most likely that’s less a technical decision than a business decision, so that you never realize the true extent of Netflix’s catalog.


It’s obviously not a technical decision. Rights holders wouldn’t allow them to stream anything beyond their contract and I’m sure they have at least one team responsible for making sure videos are only available during the contract period.


Personally, I found that on my oldish (Sony X900F) TV Netflix has become faster over the years, while the rest of the (Android) TV has become slower and slower, up to the point where now apps (that once worked perfectly) now are buggy, don't open or require a Wi-Fi adapter restart.


It is surely solving a promotion problem and a bonus-getting problem for someone in their hierarchy. Plus it is making the world a better place through constructing elegant hierarchies for maximum code reuse and extensibility and through minimal message-oriented transport layers.


I have a lot of experience with GraphQL and I love it. It saves a ton of development time.

However, for those who wonder what the disadvantages are, here are some. They are from real world production experience and they are not what people usually claim wrongly (like graphql would be harder to secure/version, ...)

No, some real pain points are:

1. Lack of a Map-type. There is no native type to return a list/array of objects but not a map with unique keys or even a set instead of a list. You can fallback to "convention" or custom types (like plain json) but it sucks.

2. Uploading big files (in chunks) is much more tricky than expected

3. There are union-types for the returned data. For example, I can query for an animal and get either a cat or a dolphin and if I use typescript or another capable language then the compiler will tell me that. But I cannot send such a request to the server, saying "here I send you an animal, the data is this ...". The server will have to provide a separate query/endpoint per animal. Very very annoying.

4. While graphql is awesome when it comes to batching requests, what it is not so awesome at is to improve performance by allowing the server to return the part of the data is already resolved. So while reducing the number http requests, now the previous slowest http request will become the bottleneck for all. This means the page might load subjectively faster because some parts are rendered later than possible. There is work going on here (like @defer) but it's not fully spec'd and also the solution doesn't work for some cases

There are more points but this gives you some idea of the ACTUAL problems. Otherwise, from development and setup time over maintenance, analytics, versioning/deprecation, tooling and so on, graphql is much better than your standard REST api in my opinion.


> Lack of a Map-type.

Why do you need special map types for transferring maps? Doesn't list of key-value pairs suffice?

Also, why am I wrong to even ask the above questions?


It's a fair question. Having a map-type has several benefits:

1. I can signal to my api's users that there won't be any repeating keys without having to write documentation

2. The type can be mapped correctly into the target language. Most languages have a map-type and so it's nice if you don't have to convert it yourself

3. No manual conversion also saves time in most cases, since libraries can do it efficiently in one step. Otherwise you get a list<X> from your library and have to turn it into a map. Not good for bigger lists in performance sensitive applications

4. The same is also true the other way around when sending data to the server

5. It saves space in many serialization formats like json. Instead of [{"key": "key1", value: "value1"}, ...] you get {"key1": "value1", ...}

6. It's nicer to read and debug

7. It's nicer to manually create/write those values in tools like graphiql to test queries by hand and those tools can even warn you if you repeat a key by accident

Just some of the things out of my head, I'm sure I've missed a bunch.


1. Pretty much that's the answer I was looking for.

...

5. I thought about something like [["key1", "value1"], ["... like in Lisp-y languages.


Yes (5.) is possible, but now your API type becomes "List of List of String" and you need documentation and examples to explain that every list will have two entries and the first one will be the key. On top of that, if you have a different types for keys and values you have an even bigger problem, because lists in graphql need to have one type for all elements.

And while you can use a uniontype (like String | Integer) to have strings as keys and integers as values, your user now ends up with an ugly typ in their code and has to untangle it by hand.

So the user will have to 1.) know about that it is supposed to be a map, 2.) untangle the list types in their code, 3.) convert it into a map while not mixing up key and value

Therefore I usually go with explicit key/value objects if it's okay for performance or go with a custom JSON type if performance trumps the rest.


I see, GraphQL definitely needs maps and tuples then.


I created a proposal for Map type but didn’t make it through.

https://github.com/graphql/graphql-spec/pull/888

The issue with GraphQL is it tries to appease too many masters.

Similar to jsx. The language isn’t evolving.

The good thing is the spec is (almost) frozen, so there’s many implementations, the bad is it can’t encompass the flexibility of json schema can do.

Going with GraphQL means you have to have good control over both client and server. And like any tool, there are new ways to shoot yourself.


A (single-level) Map is generally understood to have unique keys, which allows for some invariants derived from this property, such as a one-to-one or one-to-many object relationship, without runtime checks in client code.

I do think it's worthwhile to ask the question, though. I have a strong personal preference to avoid encoding invariants like this in wire representations, because they are properties of the _schema_ and not the wire type (JSON object, in my most commonly-encountered case).

Of course, the entire point of GraphQL is to encode invariants in the data schema, so it's entirely reasonable to ask for a built-in Map type instead of building your own for every project.


JSON (as defined by json.org), for example, does not specify that key/value pairs need to be unique. ECMA-404 explicitly calls this out as an implementation consideration. I know of one implementation that supports multiple entries with the same key.


> It saves a ton of development time.

Could you expand on this? I have had the completely opposite experience.


Why don't you explain your experiences first so that we can learn from what you found were drawbacks?


This is a sad but expected day. For years i seem to have been the last lonely falcor user who is still excited about this and thinks this is one of the best abstractions for a key class of state management applications, that are not a great fit to graphQL at all.

- Falcor can be schemaless with optional json schema where it makes sense

- Falcor supports simpler to reason about and implement features that map perfectly to javascript objects so you can do zero boilerplate databinding with ES proxies without writing query and mutation wrappers

- Does not try to be a qyery language but only expose things you need to request the data that needs to be rendered in the UI

I think not even the creators of falcor fully understood how perfect it is if you just add in the last missing piece of fully automating the connection from the falcor model to the place in the UI templates where the data is needed. Most people tried doing this manually in component boilderplate which lead initially to preloading tens of json paths eg

    falcor.preload([`todos.done.length`,`todos.done[0..10].name`, 
    `todos.done[0..10].date`, ...etc.])

and then people developing GraphQl like syntax for these eg. somthing like

    load(`
     todos { done 0...10 {name, data} }  etc.
    `)

at which point devs thought they might as well be using graphQL and get more features

The key mistake was that you need to instead think about your UI components ITSELF as the data quueries eg you can automatically derive all falcor quieries from a component like this without ANY boilerplate, and this is only possible with falcor, as everything else has so many features that it would not be possible to map the UI code to the intended data queries

    {#each todos as todo}
       <div>{todo.name} ({todo.date})</div>
    {/each}

It does not look like netflix will hand over falcor to a community and the codebase needs lots of work especially around tooling and overuse of some patterns like a custom observable implementation but i am still on the fence about building a new minimal derived library or forking


I don’t see the value ins Graphql. Most apis rarely change and the complexity of supporting queries is not worth the time saved.

Graphql was a cool experiment, but I’m sticking with rest/protobufs


The original motivation was to reduce the number of network requests made on cellular network-connected mobile devices, both to save on power consumption and reduce latency for the user. It off-loads a lot of complexity and computation from the client to the server, and make sense if want to create as good a mobile experience as you can.

In terms of code architecture, it drastically simplifies frontend code, and overall reduces backend code and boilerplate. It's extremely elegant and nice to use over creating custom endpoints for every use-case, but the N+1 SQL query problem is a giant thorn.


Kinda, by all accounts the original motivation was to solve the proliferation of endpoints. Everyone was already writing per-screen endpoints to solve the network requests problem (which, contrary to what many believe, wasn't magically solve by http2), but they were doing it in a way which played out in several ways:

1. Having to make a new endpoint every time your frontend changes

2. Not making a new endpoint, and just augmenting the existing one for a screen. Which would cause them to accumulate dead data over time (especially if multiple app versions had to be supported concurrently -- in the case of Facebook this was ~3000 versions).

3. Being lazy and finding a similar endpoint meant for another use case and piggy-backing it for your new usage.

All of these would create maintenance and organisational problems.

GraphQL is essentially a system that lets you write endpoint specs (in the form of GraphQL query documents) that the backend knows how to support. It's not a free lunch, you still have to do a lot of work on the backend to allow it to do this efficiently and securely (nowhere near as difficult as people make it out to be though), but it does a really good job at solving the endpoint maintenance problem.


You can still design an immutable REST api to match the client's needs. Apollo has really nice out-of-the-box caching that can be tricky to replicate with rest.

I see your point about reducing network requests (graphql lets you co-mingle mutations and queries), but I don't think that feature is used often enough, b/c what if one query fails, then everyone has to fail).


> Apollo has really nice out-of-the-box caching that can be tricky to replicate with rest.

Caching is trivial to do with REST.

The "really nice caching" that Apollo does literally deserializes and deep inspects both the request and the response to try and figure out caching on specific fields. Also, POST requests are not cacheable according to HTTP spec.

With REST you set an ETag and/or Cache-Control headers and let your existing infra and client browsers handle that.


You can make a REST endpoint match a client's needs, but if you have multiple clients (for example, 1 for mobile and 1 for desktop) that all need different amounts of data (for example, the mobile client shows a simplified view with less data), then you would need to write 2 different REST endpoints to handle each clients. Multiply that by the number of pages with a difference.


> then you would need to write 2 different REST endpoints to handle each clients.

Or you use Accept header for its intended purpose

Accept: com.company.user-aggregated/json

Accept: com.company.user-aggregated-lite/json

etc.

And let the server return the fields defined by the relevant schemas.

I mean, the advise given for GraphQL in prod is to literally call predefined queries only.


> It's extremely elegant and nice to use over creating custom endpoints for every use-case, but the N+1 SQL query problem is a giant thorn.

Having not used, but only read about graphql, this was the first thing that struck me. It seems great at minimizing data transferred to the client, but it doesn't (seem to) stop that data being fetched from the DB - it just post-filters it.

I'm imagining a scenario like a dashboard, where you're getting a small amount of data from a lot of places. With REST, we'd generally do that by having a dedicated endpoint for the whole dashboard that executes a single query, letting the DB do what it's good at (efficiently retrieving required data). My naive impression is that graphql would execute a bunch of queries, trim what's not needed and join it all together. With anything non-trivial that seems like a performance nightmare.


> but the N+1 SQL query problem is a giant thorn.

It's worse because in a big system this becomes N+1 API calls to other systems (each with their own permissions, latencies, caching etc.)


For an API that centers around filters and nested subfilters to retrieve exponentially specific data, graphql can end up saving you a lot of work.

For anything else, it seems pointless.


This is cool, but why? What’s the business use case or problem they’re trying to solve? I would have liked to hear about that. Without that critical piece, it sounds like Netflix engineers spent a lot of time and effort just to migrate to a new framework.

It also bears mentioning that Netflix is, or pretty much should be, complete. They don’t need to make any changes to the service; if so, it’s very few. I’m sure they need talented engineers to scale up their operations, and great SREs, but what are they still writing code for?


This has been a perennial question about Netflix for a while now: they've tended to want to brand themselves as a tech company, but that hasn't been true for a long time now and was questionable to start with.

If they were a tech company that'd be a SaaS provider for video streaming, in which case all of this would make sense - the proliferation of streaming providers certainly provides the use-case that someone could offer that as a branded service. But the time for that has come and gone as well - the other streaming services exist, and they work fine.


The business case seems to be to finally kill Falcor [1] which had a lot of similarities to GraphQL but a much smaller maintenance and developer community than GraphQL and I would assume looked a lot like tech debt to Netflix at this point.

[1] https://github.com/Netflix/falcor


I wonder how many hidden n+1 problems there are. Reading the blog post, it looks like they mostly only tested existing pathways as part of the migration. Who knows what random requests could do.


Dataloader (https://github.com/graphql/dataloader) eliminates many n+1 issues. Basically, entity requests are queued up during evaluation of the query and then you can batch them up for fulfillment. It’s a great addition to other asynchronous contexts as well.

WRT random requests, there are libraries for query cost estimation you can use as a gate.


Interesting, hadn’t seen that package, thanks. The general pattern seems quite useful, is it implemented in any SQL ORMs?

Seems like you could do the same batching/coalesce strategy for async Postgres for example, but I don’t see anything after a quick scan of the docs in SQLAlchemy. (Seems like it would be feasible since they already batch requests in unit-of-work, they just don’t coalesce to bulk operations AFAICT.)


Using something like `pothos` for your graphql backend, you can get tight integration with `prisma`, which will practically eliminate any N+1 issues.

For fields which hit external services, you can define types as "loadable" so that every time those are requested in a batch, they are loaded efficiently to avoid n+1.


Correct, there are solutions out there, but unknown if they implemented them.


Yes, this is the biggest problem with GraphQL that I haven't addressed anywhere.

The architectural beauty of GraphQL is that you can write isolated, functional nodes that only have to know about their object type. For example, the User node only has to know how to get the user's last_login, active status, and return a reference to another node type like a profile Image.

Inside the User node, you are free to write code (e.g. Java or Python) that can compute which Image node is the right one to return. i.e. you can write:

  class UserNode:
      def get_user_profile_image() -> ImageNode:
          return some_arbitrary_function()

There is no way I've seen to square this kind of arbitrary node computation with the desire to write an optimized SQL query that selects all needed information in one big-ass statement.


The exact same problem exists in an typical REST api as well. In both cases you have to add a specialized endpoint to retrieve multiple results.


You could use https://github.com/join-monster/join-monster, but setting that aside it's usually enough to use Dataloaders that resolve based on some source ID, with some server-local caching on top if latency becomes an issue.


This is Netflix, not some amateur-hour implementation copied from a blogpost.

The de-facto GraphQL Java library comes with dataloaders built-in anyways:

https://www.graphql-java.com/documentation/batching/


While Netflix has a good reputation, we should not give blanket benefit of the doubt, especially since the parent comment was a rather interesting and inquisitive one.


Is JS/Express/Apollo still the goto graphQL server implementation or C#(HotChocolate), Java, go etc are widely used too? On the client side(for mobile), AFAIK iOS(Swift) and Android(Kotlin) does not support GraphQL natively? are there 3rd party libraries that can be used?

Edit: Added Apollo


The "go-to" GraphQL server implementation varies based on language.

Here are the popular ones to my knowledge:

- Node.js: GraphQL Yoga + Fastify, Apollo Server

- Java/Kotlin: Netflix DGS (built on top of Spring Boot)

- Scala: Caliban, Sangria

- Python: Strawberry, Graphene Django

- C#: HotChocolate

  > "On the client side(for mobile), AFAIK iOS(Swift) and Android(Kotlin) does not support GraphQL natively?"
GraphQL queries are just HTTP POST queries with a JSON body. They're supported everywhere.

If you want specialized tooling for them, Kotlin and Swift both have great strongly-typed GraphQL libraries.

Apollo publishes libraries for both:

- https://www.apollographql.com/docs/kotlin/

- https://www.apollographql.com/docs/ios/


> Java/Kotlin: Netflix DGS (built on top of Spring Boot)

Is that really popular? I'd rather use graphql-kotlin (expedia), graphql spring (yes, recent Spring module), quarkus graphql (code 1st) or just about anything else than that...

> Node.js: GraphQL Yoga + Fastify, Apollo Server

Typegraphql is / was hugely popular; there's also an Express based Graphql server

Aside: there's also Rust and async-graphql


Apollo is also available for Elixir, where I have seen it much loved.


It appears that fastify can't keep their website up.


Apparently something got messed up with their cloudflare setup and the person with access is at a wedding or something.

https://twitter.com/fastifyjs/status/1670145210347577344?cxt...


I've been using json-api with graphiti in rails. And I gotta say the massive gain from it is that it's all rest and a trivial client impl from scratch if necessary.

Couldn't recommend it more.

Have to say. Most json-api impls suck, so graphiti has been a game changer for me.

N+1 are a problem buuuut it forces you into good model designs and good tools like graphiti and the latest rails show you the cause of the n+1s so it's not so bad to debug.


We've been using Hotchocolate for over a year now I n a project. And the experience has mostly been pretty good.

And pair this with their Blazor client called StrawberryShake. And your production levels are pretty nuts.

So to answer your question, yes people do use other alternatives


Curious how they handle GQL injections. Most devs using graphql have no clue what they are as the majority just cargo cults new frameworks to keep themselves busy.


What are GQL injections? You mean something like SQL injections that come through the graphql API?


Exactly. Suppose you have a front end system that captures user input, and then the backend communicates with another system using the input data. If not properly escaped and is concatenated then it can lead to an injection attack just like regular sql.


I find the terminology strange.

The exact same can happen with a standard REST api. In fact, it's even more likely since there is no type system to assist there.

Would you then call it REST injections too?


> We migrated Netflix’s mobile apps to GraphQL with zero downtime

Is "zero downtime" relevant here?

For example, when migrating a database that is the source-of-truth for data, then yeah, downtime is something you have to contend with. But for a client-server API change, isn't it trivial? Companies do this all the time -- expose a new version of an API then gradually migrate clients over.

(It's definitely not a trivial task overall! For example, you need thorough testing to make sure you don't break existing functionality and the article does talk about that.)


I don't know, you said isn't trivial then you said it's not trivial! :D It's a colossal effort if you are at Netflix size, they support probably the largest number of client devices on the planet.


I think the important thing for people to recognize is that Falcor, the tool used in their mobile apps, was already GraphQL-like. So, this isn't a giant change.


The main article does not mention in detail why the decision was taken to use GraphQL. But the HN comments are a treasure trove right here.


Falcor was cool. I'm sad seeing it go away.


I would not say it is more going away now than in the last 2 years of not getting upstream support from netflix. If anything this step at least makes clear this is a dead end at netflix and we can think about how to go forward with what is/was great about falcor!


Maybe now GraphQL api can stop auto completing movies that does not exist in their catalog.


?

It autocompletes so you find out more quickly that Netflix doesn't carry it, and what similar options are

I get that you are annoyed Netflix didn't have the movie you wanted, but autocomplete doesn't make that worse.


I don't look for similar movies, I look for the exact movie I want, it's just a redirection of their poor catalog. If that was the intended use case, they'd have proper catalogs to drill down instead of a very long, arbitrary vertical canvas of always changing, non consistent categories.


Sounds like a personal preference.

When I search for "How to Train Your Dragon 2", I find Netflix doesn't have it.

But it has the original, plus a few series, so I turn on one of those instead.


You’re right, but it’s annoying for sure. Instead of telling me they don’t have a title, they complete its full name (as if to say „I know what you want, but I’m not gonna give it to ya“), yet show me some arbitrary stuff named similar.

It’s just a poor solution.


Usually, the search results are movies with similar genre to the one I was looking for, not just simply similar spelling etc. I assume they look up stuff like what other movies people who had seen the searched-for movie have seen. So if I was looking for Movie A and Netflix knows that people who've seen Movie A tend to like Movie B, C, D, etc (and these are available in your part of the world) it'll show these movies instead. I think this is nicer and better than just failing with zero results.


A lot of the sentiment coming from non-gql people in this thread start with: "gql is impossible to X, Y, Z" which is immediately untrue by inference if you base it from how well existing companies in the wild have adapted to it, and provable on your own if you just went out and tried it yourself.

"from what I can see in the landing page, REST can do everything it does anyway" is partially true, but is not useful, because how else would have gql picked up adoption if it can't provide similar benefits as REST? I'm smelling a lot of cope from people who have buried their heads so deep in the sand that they cannot fathom a world that doesn't prefer REST anymore. At least try the tech for your own and make informed opinions.


My problem isn’t that graphql can’t do X. It’s the opposite, that I don’t know what it’s supposed to do really well – the core value prop. I still haven’t heard any one-sentence explanation of what it is, and importantly, what it isn’t.

To me it sounds like they try to solve numerous problems: (1) be a query language, ie an improvement over sql, (2) a type safe alternative to REST ie web APIs (3) allow frontend developers to write queries without having to write endpoints, (4) keep clients lightweight, (5) be a single entry point to this hyper graph thing, and more.

None of these things seem compelling in isolation: simply replacing REST adds resolver complexity and doesn’t handle things like file uploads. Substituting sql restricts you to whatever sql is generated and you end up with two query planners. Allowing frontend to query db directly is insecure so you must have fool proof row level security or more resolver complexity. Clients I guess started out thin but now there are all these intelligent caching layers. And this hyper graph thing is only valuable with other graphql services.

So, I guess graphql can be good if you marry it and go 100% all in? But to me it’s a smell when technology claims that your pains can be resolved by using more of the same tech. How am I wrong?


It's perfectly fine to use graphql for fetching metadata and then using REST API for file upload and downloads.

On a gql server, you implement resolvers for the schema. There might be some frameworks that abstract SQL away from the resolver implementation but a resolver may need to make a combination of sql and network calls to other services. Or only network calls to other services.

> Allowing frontend to query db directly is insecure so you must have fool proof row level security or more resolver complexity. I'm not sure why you are thinking that graphql means the frontend is querying the db directly; a graphql server implementation is implement a callback for each graph node that returns the object. It's the server code logic to implement permission checks and the actual SQL or network calls to resolve the object. What part of this results in frontend code querying SQL directly?

It seems like you are getting caught up in the name of "query language" which may be partially a misnomer. It's more like a data fetching protocol


(You missed a line break so my quote extended into your response).

> It seems like you are getting caught up in the name of "query language" which may be partially a misnomer. It's more like a data fetching protocol

Yes, I gave multiple definitions and that’s one of them (2). While that’s certainly true, is that how it’s used in practice and sold? All popular frameworks I’m aware of are selling themselves as having automatic db resolvers with SQL dbs. And thus fast frontend iteration. N+1 solution. Etc.

> It's the server code logic to implement permission check

Isn’t that very difficult to do? Resolvers have recursive relations that can be very tricky to secure, since it’s a high abstraction level. So you tend to rely on RLS or another system to be configured, no?


> Isn’t that very difficult to do? Resolvers have recursive relations that can be very tricky to secure, since it’s a high abstraction level. So you tend to rely on RLS or another system to be configured, no?

I really don't think it's any more difficult than if you're not using graphql. If you're hitting a db then you can store auth/permission context for the lifetime of the request. Each time you hit the db to resolve a node, you're going to use the same types of patterns you'd use when fetching objects from the db using sql or an orm. It's customary to have a request context object available in all of the resolvers for just this reason.

If you resolving by calling other services, auth scopes would typically be forwarded on in request headers.

> All popular frameworks I’m aware of are selling themselves as having automatic db resolvers with SQL dbs.

I think I agree if some frameworks for full stack aimed at prototyping where a solo frontend-focused developer needs a backend it abstracts too much, including the db. In these cases, it's probably unnecessary and if you're solo dev on a full stack framework and probably doesn't matter either way.

I've worked on graphql at scale as an frontend service that acted as an API gateway of sorts. The resolvers were not accessing the db but calling other services.

When working on a new application, I would probably use REST and probably would be a long while and would need to have a set of problems to solve with graphql. I think it's quite good at federating services.


> simply replacing REST adds resolver complexity [...]

To put it simply, even with REST, you're already dealing with the concept of "how does clients get a handle of a particular entity?" With REST, the answer is usually muddled by client data fetching mechanisms and backend architecture that you've opted to use - so just because two projects are doing REST does not mean they're handling these entities in a similar, understandable nature and it requires a lot of background context, same with auth.

graphql makes all that a deliberate matter instead. So take whatever's in your db, decide which fields are you going to expose, and write resolvers that return just that - you can't get any more foolproof than that, it's basically the same thing you do with REST, just without all the client-side fumbling and coordination.

But what I'd argue the thing it does best, is that with REST, you'd probably write code for handling Entity A, and if Sub-Entity A and B rely on Entity A, you'd probably write specific code to ensure the right entities are returned in your endpoints. With graphql, you just reference that entity and it's resolved automatically, because you have written the resolver for that entity already. Resolvers have access to the parent entity that's referencing it, so if Sub-Entity B has stricter controls in what it should expose, the Entity A's resolver can be written to accommodate that (see directives among other ways for how to scale this better).

As for auth, whatever middleware you're already using in your REST endpoints can also be reused one way or another for the gql endpoint, no issue.

> this hyper graph thing is only valuable with other graphql services.

Even without other graphql consumers/services, there's huge value in not having to write multiple ways of handling a certain entity anymore, among other things.

> So, I guess graphql can be good if you marry it and go 100% all in?

All of my recent work related to graphql happened in projects that incrementally adopt it - there's no requirement whatsoever to fully commit to it 100%. It definitely helps that you can reuse whatever your REST endpoints use to comprise code that builds up towards resolvers, like util/helper fns. Nothing stops you from serving the same entity in both REST and graphql forms, heck there's specific usecases that benefit from it (i.e. maybe your mobile app can't keep up with it yet, and you're trying it out for web for now etc)

Say, in such kinds of projects, what I can recommend is identifying a subset of entities that your backend serves that you think (at least superficially) will benefit from it e.g. a relatively new entity that is essentially WIP across releases, and you'd benefit from at least not having to redo the entire REST API endpoint subset for this entity whenever you're making drastic changes, or a particularly old one that could use a rethinking anyway, among other use cases. After a couple of releases you'll get a feel for how it works, and then it'll be enjoyable to port more of the entities later on.


Thanks, this is really informative.

> decide which fields are you going to expose, and write resolvers that return just that

To be clear this means writing custom resolvers? That seems like the most sane way to use graphql, should I ever revisit it.

What’s the logical authorization entity? In rest, it’s (typically) the endpoint itself. What is it in graphql? Does a specific entity resolver have authorization? What does it look like in pseudocode?

How hard is it to write custom resolvers that also produce efficient sql? A gql query can be arbitrarily complex (ie nested), no? How to curb that complexity in practice?


Hmmm I'm not aware if the word 'custom' applies to resolvers - to an extent, you're always going to write them out as such for optimal benefit, can't imagine a non-custom one if that's what you meant.

> What’s the logical authorization entity? In rest, it’s (typically) the endpoint itself. What is it in graphql? Does a specific entity resolver have authorization? What does it look like in pseudocode?

You can have both API-wide and resolver-defined auth. In your graphql server config, there's a `context` config option you can pass a function to, and it has access to the whole HTTP request (typically, depends on the integration but I assume all of them treat it the same), it's where you'd probably e.g. check for auth headers and run them against db or the cache layer for auth etc. You can already throw errors and whatnot within this function, so that's the API-wide part.

The returned value of this context function is then included in the params of any executing resolvers, so you can have that resolver throw if e.g. the user stored in context does not have the sufficient roles to access this entity.

There's also directives: say you want to have an `@auth` directive that you can just slap on typedefs that makes auth logic reusable across a subset of entities, but you don't want to handle it on both API-wide and resolver levels, you just write a transform fn, register it in the config, and put that directive on the schema itself.

> How hard is it to write custom resolvers that also produce efficient sql? A gql query can be arbitrarily complex (ie nested), no? How to curb that complexity in practice?

Yes, a gql query can be complex and nested, but you only need to write the resolver in a way that all the ways you need to resolve that entity are taken into account. A query resolver returning one instance of Entity A via their unique ID in most cases is enough, for example - it does not matter how deep into the gql query the entity appears, graphql will do the heavy lifting and refer or run every resolver fn until all entities in that query have been resolved.

The next question is, that means graphql will hit the db one-to-many-times depending on the schema, and yes, that'll happen, but there are again, granular ways to handle that depending on the integration - Apollo at least lets you configure your own in-memory cache or use Redis for example, and be able to cache results in the schema-wide, resolver and response levels.


Not once have I seen a graphql blog/usage since like 2018 onwards, just die already


How to avoid N+1 query ? You don't join SQL.


The most common practice is to turn N+1 into 1+1 using dataloaders (https://github.com/graphql/dataloader for JS, there are equivalents for most implementations). The N resolvers invoke a single batched loader which receives a list of keys and returns a list of values.


I am not sure I understand that n+1 select issue with graphQL.

On my project, we generate SPARQL queries [to simplify, it is not so different from a GraphQL query] and we send it to a SQL translator that then sends that SQL to a Spark cluster. It is reasonably efficient, and extremely flexible.

Of course, this is a single database use case, but I don’t see any n+1 select involved here. And I do not understand how single database graphQL servers cannot work exactly the same.


brave to assume they are avoiding this problem :/


Definitely not working anywhere that doesn't have a GraphQL api. Once you've used it at scale there's no going back.


Go on…




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: