back
90 comments
From the linked article:

> With all of those caveats noted, HTTP/2 should put to rest any notion of the need to minimise the number of requests for APIs; the protocol makes them cheap enough to not practically matter. Go ahead and design a highly granular HTTP API to meet the needs of your clients

This seems highly misleading and missing the point. Sure, you can send a lot of requests in parallel with http/2. But you still incur significant latency if these multiple requests are dependent on one another and serialized. For instance, suppose you have 2 granular APIs that:

- Returns all friends for the specific user

- Returns the name, age and hometown for a specific user

Suppose your client wants to get all of a user's friends whose hometown is NYC. Even with http/2, it has to use the first API, wait for the response containing a list of userIDs, then use the second API to get all of their hometowns.

Whereas with GraphQL, it facilitates building a single API call that says "give me all friends for a specific user, along with each friend's hometown". Now, there is only one round-trip latency cost. Not two. Even with the overhead improvements mentioned, the cost of two back-to-back round-trips would be much higher. It is very odd that this isn't mentioned in the article or any of the other articles they reference.

> Suppose your client wants to get all of a user's friends whose hometown is NYC. Even with http/2, it has to use the first API, wait for the response containing a list of userIDs, then use the second API to get all of their hometowns.

Not only that, but the resulting set will have inconsistencies if the database changes between the two requests. It's very unusual for HTTP applications to maintain transactional consistency over multiple requests.

This can be a security issue among other things, and even when it isn't, it can result in the display of glitchy data, whose inconsistency persists in the client which fetched them.

For example, you get all of the user's friends' userIDs. Then the DB is changed to remove one of the friends (by that friend). Then that friend changes their hometown to a new place, that they don't want the original user to know, and expects the original user can't see.

Then you do the second API call to get the hometowns of the userIDs. The result contains the new place that you should not have been able to access, and maybe it's shown on a screen for an unbounded time after that, or printed in a report.

Similar issues occur when fetching data to sum into totals and finding it doesn't match an expected total, or expecting some logical constraint to hold for every item in the result because it's implied by the original query.

(Live-streamed query updates turn these into momentary glitches, which is still wrong but at least those disappear from view soon after.)

This also ignores things like Hasura which does global optimization by converted GraphQL into a single SQL query.
I think the Fields: header in the library is supposed to be used for that, it would look something like

   Fields: /users/*/hometown
in the same request.

It feels like it’s solving all the wrong problems to me - who actually wants to put varnish in between GraphQL client and server? Caching can be done more efficiently at either end. And this doesn’t provide a replacement for a query language, just moves some of the optimizations to the transport (http2) layer.

Now I’m wondering why Apollo doesn’t use http2 push to batch requests, instead of merging queries. Or does it?

Even directly accessing a database on localhost, your code will be slow if you send "select id from user where user.friend = ?" and then 1000 times "select town from address where user_id = ?" rather than one query with a join.
Why wouldn’t you return more data for the REST API instead of making dependent requests?
> Whereas with GraphQL, it facilitates building a single API call that says "give me all friends for a specific user, along with each friend's hometown".

Better yet, submit a request asking for all friends whose hometown is NYC (or whose hometown is the same as one of the user's previous hometowns, or...). That way only a subset of the data needs transmitting.

It's not really a valid argument, because if you only have two APIs and you can't create more, you can't switch to a GraphQL implementation in less time than you could add an appropriate endpoint.

  GET users/<id>/friends
       ?fields=friend.*
       &where=hometown:'NYC'
       &aggregate=distinct
http2 has push, so you can make a single request (for the friends of a user) and then just push all the users in that response before the client requests it. this all happens over a single connection and leverages all the http infrastructure and experience you already have
I worked with GraphQL a bit over a year and half ago on a project. I was the front end consumer, working with backend microservices via graphQL.

I wasn't sold on the GraphQL hype then, and I'm still not, but this article seems to miss the point. [Edit: I mean, it agrees, but it does so poorly]

A lot of people TALK about the lack of multiple back-and-forth, and about not wasting unnecessary data, but honestly, that wasn't a big deal. I expect there are some situations where that comes into play, but for most people the appeal of GraphQL lies elsewhere. If HTTP/2 means that's less of a big deal, I don't expect much change.

The legit upside to GraphQL was that backend could change rapidly without breaking compatibility for existing consumers. Some changes could be fixed purely frontend by changing the query, but if we needed new data that wasn't provided (or a variation on data that was provided) the backend could add that AND NOT IMPACT EXISTING CONSUMERS. That's not the only benefit (and remember, I remain a skeptic) but that was by far the biggest and was definitely real.

Even if the claims of HTTP/2 rendering the call overhead are correct (see other comments to doubt that), that has no impact on this value of GraphQL.

> I wasn't sold on the GraphQL hype then, and I'm still not,

Why not?

The biggest problem GraphQL solves is not a technical one. GraphQL is an enforceable contract between clients and servers that encourages APIs to be designed in a way that best serves the client, and in doing so, the end-user. Clients used to spend an inordinate amount of time and thought in simply getting the correct data from the server. So much so that entire FE frameworks and libraries evolved to essentially pull all the server’s data, organize it into UI-friendly chunks, and then (and only finally then) create an experience the user would find valuable. It was a small miracle if any time or energy was left to make the user experience enjoyable too.

A litmus test for a well designed GraphQL API is: could you tell what the client looks like and what the client does simply by looking at the schema? GraphQL forced everyone to think about the end-user experience, and to be on the same page. Literally. And that is it’s greatest strength.

It's refreshing that the author acknowledges the nuances around tradeoffs of using, and not using, GraphQL.

Having used REST (with swagger/openAPI), gRPC and now graphQL, the most painful thing has been the tribal militance from supporters of each, defending their own vested interest.

It's almost like different tools are useful for different things.

> tribal militance from supporters of each, defending their own vested interest.

This is something I really wish I understood before going down the road of graphql. I think it's a great technology, but the developers supporting it are making it nearly impossible for a legacy codebase to ever adopt.

Ex: so many JS codebases use redux. Apollo is a popular graphql framework that supported redux integration for some time, then suddenly ripped it out. They cited performance concerns, but I looked through the code myself and it would seem they just have a bias against redux. This issue thread makes that especially evident: https://github.com/apollographql/apollo-client/issues/2273

We were very lucky to have found that before breaking ground on the work.

It would be irrelevant only if the sole reason to use GraphQL is to minimize network hops and bandwidth. I'd argue that, if that's the only positive you see in GraphQL, then you would be just as well off writing custom API endpoints for each view of your application.

I prefer interacting with GraphQL over RESTful interfaces. From my experience, it's less prone running into bugs inherent to client-side joins of API responses, easier to evolve iteratively, and generally more pleasant to work with thanks to its introspectable declarative schema and flexible query language.

This seems like a false dichotomy. In my eyes the point of GraphQL is the query model.

HTTP2 is just a transport, you still need to put something on it, like gRPC.

Seems natural that GraphQL will evolve to use it, and benefit from the technical improvements.

I really like the server push model, but not sure how to square it with GraphQL way of doing things.

> In my eyes the point of GraphQL is the query model.

Yeah me too, I would compare restful to GraphQL and HTTP2 to HTTP1. It is also annoying that the author hardly mentions restful APIs or it's shortcomings.

Can someone please explain what GraphQL actually is? I've looked at it multiple times but never got super deep... my limited understanding is that all it is is basically defining a schema so that when issuing API requests, the client itself can make it's own "query request", rather than talking to an app backend which has SQL queries programmed/written in an ORM or some database wrapper.

I feel like I'm missing something, as that seems incredibly limited, especially with things like performance (where queries need to be tuned and refined and custom written. Just a simple SELECT * FROM X INNER JOIN Y and horrible N+1 isn't good enough)

Can someone please explain what is GraphQL once and for all?

Yes - (and totally reasonable question, btw - it's remarkable how hard it is for the folks behind it to just plainly state what it is vs. coating it in buzzwords).

BTW - I may be wrong / misunderstanding something here as I'm only in the research phase, but here's what I got:

GraphQL is an alternative to REST as a way for clients to query servers for information. In a REST query, you hit an endpoint and add optional query params. But you get back results based purely on what the server has been singularly designed to give back. For example, if I query:

GET /users/1

I'll get back a user object that the server has been programmed to return. It's of course possible to customize this with query params, and do something like:

GET /users/1?only_include=first_name,last_name

But that's the exception to most RESTful APIs, not the norm.

In a GraphQL query, the client specifies _exactly_ which fields it wants back, and that's baked into the design. So the client would submit a query like this:

{ user(id: "1") { first_name last_name } }

And the server would return exactly the object the client asked for.

There's no magic here -- that's the part that many people have trouble explaining. When you write your GraphQL server, you still need to write the actual queries (<--- this is the key!). But structurally, you write more generic queries -- you'd say "when a client requests a user, run this SQL", "when a client requests first_name on a user, run this SQL", etc. etc.

That way on the server, you write isolated query resolvers (called, amazingly enough, resolvers), each of which get run when a query comes in.

This is as opposed to a RESTful approach, where you'd do a more traditional single SQL query for the /users/:id endpoint (SELECT * FROM USERS WHERE ID = ... )

Hope that makes sense (and is accurate!)

GraphQL allows you to not only fetch a single piece of data, but allows you to also fetch related data, ie traverse the relational graph of data. So if you have friends, and sometimes want to fetch your friend's latest posts/pictures, you can do so as you like with one single query. In REST, you would first get all your friends, then for each of these friends get all the posts/pictures as individual queries.

In short: it allows you to query a database much more naturally in one go, rather than having to fetch data, and depending on that data then fetch more data. On top of that, it's typed, relatively easy to learn and well documented. I'd highly recommend it, even if it's a tad more complicated than plain REST.

Basically GraphQL is an API contract between a client and a server. The contract defines what data, through types and fields, is available.

The server must fulfil this contract by providing methods (called resolvers) for each field.

The client must fulfil this contract by only asking for available fields.

The query language is built to support highly nested data.

Now, the N+1 problem you are talking about is not a GraphQL problem, but an implementation problem. Depending on how you write your server methods you can get it down to very few db calls (some use a thing called dataloader. Other tools are hasura or postgraphile)

It's like a dumbed-down version of SQL for clients to query the server. It's not totally arbitrary, it kind of let's you tie together micro-requests. You backebd might be using an ORM. It might be pulling data from 10 different places and exposing them in a single api. Optimisation can be an issue.
GraphQL seems to be mostly touted as "You can do richer queries!". which is definitely true, but not the key factor of what makes it awesome in my experience.

Much more important to me is how it allows the backend and frontend to work closer together. I can simply send the frontend developers my schema and then they know exactly what each endpoint returns, down to the exact type of the returned keys. There's no more back and forth on what the data for a new endpoint is supposed to look like. Either the backend devs take lead and hand a schema to the frontend devs, or the frontend devs take the lead and hand a schema to the backend devs.

Other than that there's quite a lot of really cool tooling. On the backend (python/django) I'm no longer needing to write long-winded serializers for each specific kind of view. I can simply make a query object that returns the right database query. On the frontend (typescript/react) they no longer need to write types for each API view, they can simply hand the schema to a code generator and get a file out declaring all the types the API deals with.

GraphiQL is awesome for both frontend and backend devs, At the very least it's a tidy small editor for queries. It allows you to run queries as you're developing or testing views. The documentation pane shows all the return types and expected arguments and types even if you don't put any effort into documenting anything. If you do put effort into documenting it becomes a powerful API documentation that's be easy to keep up-to date.

We're still in the early days of using graphQL but what I've seen so far certainly is worth the growing pains we're going through. The only real nitpick I have is the poor documentation of graphene-python, quite a lot of crucial use cases have you running around stack overflow and the source code to find answers. The case that gave us the most trouble so far (backend and frontend) is what to do with errors. We've gone the route of having views returning a union of the result and a global error type, which seems to be working nicely so far.

Of course the richer queries are nice too, but for us they seem to be mostly limited to making queries return less info when possible. e.g. when querying users you don't always need to return the entire user, which graphQL supports nicely, allowing you to elude profile photos or other expensive-to-calculate-columns whenever needed.

I went to a talk where it labeled it as halfway between a dsl and sql. I haven't used it in about a year.

``` user { id, first_name } ```

would on the back end map to a function that runs something like.

``` select id, first_name from users ```

So the fields are dynamic in a way. Allowing you to select only the data you want. You can also nest data calls, like joins.

``` user { id, first_name, user_profile { bio, recent_comments } } ```

This would execute the above. Then take that user object into a query context. That query context allows you grab any elements from the parent returned object. I.E. the user id.

That would then execute the nested query like

``` select bio, recent_comments from user_profile where id = $user.id ```

So instead of rest end points. You are building a number of functions that return an object. You can then define relations that operate off of those returned objects. You can also restrict queries in production. So only white listed / approved queries are run.

A schema is a list of all these objects that may be returned and their relation also including type. Instead of a reverse proxy like nginx. There is schema stitching. Which combines all the schemas into one big schema. When querying it will proxy the respective calls to the respective back end services.

I did a talk on GraphQL a bit ago, so it may be out dated.

https://blog.animus.design/kotlin-backend-presentation/

Corresponding repo

https://gitlab.com/AnimusDesign/KotlinIMDBDemo/blob/master/a...

I've not used Graphql in production. When I was researching it's ecosystem anything outside of JS leaved a bit to be desired. That being said. It's a solution to a problem.

Openapi can generate clients. But if you need to make six calls. It's not performance or transit time. It's cleaning up the errors on that. Waiting for one to respond then another. From that vantage point I see the benefit. One query get what you need. If anything fails along the way it stops. It shifts the error checking pattern to the server.

Additionally in react and even mobile. There are redux or state machine stores that operate strictly off of graph ql. You've now centralized data retrieval, and state management of the app. That's a pretty big win.

https://www.apollographql.com/docs/react/data/local-state/

All of this is very beneficial to the front end / mobile. Easing data retrieval, being more expressive and type safe. But it's the front end driving how data is presented and stored to an extent. By using graphql to get the best support you should be running on node.

Build the data request you want at the client rather than the server
In a discourse where GraphQL is just an additional layer over "REST" services to make sense in terms of network roundtrip, and similarly HTTP/2 server push is used to bundle multiple "REST" results, it's worth noting that there's always the option to use more unopinionated approaches to request/response payloads such as RPC- or SOAP-like protocols merely seeking to model payload syntax without implied semantics and restriction to "GET"/"PUT" primitives. Locking your response semantics to network interactions such as in "REST" never made sense from an engineering PoV IMHO.
We've been developing a GraphQL api for the past few years and I really really really like using GraphQL. From a developer experience perspective, it's so much easier to work with than traditional REST based API's. I could add more but I'm pressed for time and I simply wanted to leave my +1 comment for GraphQL. Happy to answer follow up questions (if any).
Uh, main feature of graphql is a graph cache and graph model itself. It has nothing to do with HTTP2.
That's basically what the article says though. The connection to HTTP2 is that they both try and minimize the amount of requests made to a server. The author is just pointing out that GraphQL has more to offer than reduced requests.
GraphQL has nothing to do with graphs and caching GraphQL is an exercise in masochism. And it's not even a query language in the sense of SQL. It's just about the worst named tech we currently use, IMO.
Ignorant here: why not just use a subset of SQL?

It needs a filter and it definitely needs to be applied to a limited, custom view of the actual underlying data, but… that’s what you have to do anyway with a REST or GraphQL API.

By the time you’re done making your REST/GraphQL API “really flexible” couldn’t you just build an SQL filter?

All the APIs I used to so far are so limited. For example there’s no easy way to query multiple posts at once on GitHub’s GQL while that could have be an extremely simple `SELECT title FROM issues WHERE id IN (13,57)`

Or you could use a zero coding backend solution on top of a database like Hasura or PostGraphile.
It's bad to write SQL queries on the client side :-)
Title sounds so wrong that I'm unable to click on it.
Totally. doesn't make sense at all. Sounds like "Are burgers still relevant in coffee-table world"? HUH? What the f did the author smoke before writing that?
This is an interesting article!

A few weeks ago I found an interesting open-source project that tries to combine the best of GraphQL and REST, though it's more tilted towards REST.

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

We haven't switched our API over just yet, but are planning to do so.

Graphiti is based on the JSONAPI standard. While Graphiti is an awesome library (the author is one of the most supportive devs I’ve experienced with OSS, rivaling most paid support I’ve experienced), JSONAPI has existed longer than GraphQL, and has virtually no relationship with GraphQL or how it functions.
1. Depending your database technologies, queries are still going to be more efficient with batched operations.

2. HTTP/2 doesn't make latency/speed of light zero.

3. Outside of performance, GraphQL is a type-safe, error-minimal way to perform joins and searches.

What about HTTP/3 for your second point?
I'm a reluctant user of GraphQL. I can't specify any deep technical reasons, I just prefer a lot more control over interfaces - particularly where I'm in control of both the client and server.

But. I use GraphQL. GraphQL is a whole toolchain around client-server interactions. (IMHO) It's a pain to get started using is, but then the benefits of tooling start to compound.

HTTP2 won't replace GraphQL. Perhaps a set of libraries that use HTTP2 effectively. Even then I'd be surprised if it was a huge departure from GraphQL fundamentals - but you never know.

One problem I see with Graphql, in general, that it seems like it amplifies a problem which is something all OXMs inadvertently do. And it is the problem of managing business logic. And from what I can see is that graphql now pushes this to the client and erodes the server side’s encapsulation of business logic. Now you have the problem of having business logic everywhere? Isn’t this something we have learned throughout the years is a bad thing?
It would seem to me as a casual observer that GraphQL is more an alternative to SQL than it is to HTTP2. No?
AFAICT, the point of GraphQL to get an API that corresponds to your React state tree, so that there's much less mental overhead from client developers who don't want to deal with multiple shifting data representations.

Batching almost seems like a nice-to-have.

I guess in theory we could take a gql query like:

  query {
    user {
      first_name
      last_name
    }
    settings {
      debug
      paid
    }
  }
could be translated into:

GET /user/first_name GET /user/last_name GET /settings/debug GET /settings/paid

And you could represent any gql query as a multiplexed http2 call. And you could then have the server use a persistent user scoped dataloader (or some other shared cache) to resolve all that data and respond to each of those queries.

That's roughly an isomorphism between graphql and http2.

GraphQL has a very specific cross-functional advantage: it provides a spec for data access, to cut down novel design (of APIs) by backend and frontend.

If Backend have few data entities, or the requirements are extremely clear, your team is not likely to get the full spectrum of benefits.

If you have a large number of existing Backend data entities, or expect a large number to be created - GraphQL is a very handy spec. But if the Frontend/Product are EXPLORING how use the data, and unsure exactly how to best utilize the data types, OR they are supporting many permutations of APIs, GraphQL is a game changer. Write a python decorator to generate resolvers...

- and BOOM, Backend and Frontend will never have to negotiate over a rigid & novel API contract again.

The other stuff, like introspective documentation, sophisticated Frontend state management, and so on are great conveniences, but are not the point.

As far as HTTP2 and Frontend goes, I'm excited as it solves a fundamental networking problem. And theoretically saves us from having to bundle. But this is not what I personally consider a big Frontend problem.

In most large webapps with network-connected components, you don't want each component to make a discrete network call and pump its data straight into the component. Often you will want to use the response and update a global state, to ensure nothing is out of date. This encourages you to colocate your network logic, with some facilities for this. The GraphQL ecosystem ticks this box. Additionally network requests are a complicated flow, due to APIs having different semantics, needing to shunt value objects through promise/callback chains and the need to covering various edge cases. This encourages codification of network logic, which again, GraphQL does a great job of.

This is of course quite complicated stuff, and if you don't need the Frontend magic - you can just put your GraphQL query on a fetch, and use it like a REST endpoint.

And of course - if you don't really need the spec, I'd say think very hard before adding GraphQL.

That said, big fan of HTTP2 (although last I looked, the perf envelope created by plotting no. of connections against speed, the shape told me "don't rely on this yet").

Having built a lot of react apps with and without flux/redux, I would say the best part of GraphQL is the simplification of SPAs. Building up the query with fragments and colocating data fetching with the component that need it, is a huge win. If you have lots of micro services or even a few SOA apps, GraphQL is “developer ergonomic” win.

Majority of the latency/bandwidth wins can be achieved with a well architected jsonapi. This should not be your only reason for choosing GraphQL.

GraphQL is barely relevant today with the older HTTP standard. There is a very limited use case for GraphQL, and you most likely don't need it. If you are new to GraphQL I would recommended simply trying to use it to delete an item by Id. While this is a trivial task if you were using the MongoDB with Node/Express.. just and the GraphQL Layers.. and see all the extra code you need..