Live data from Hacker News

REST vs GraphQL vs gRPC

danhacks.com

121–130 of 168 posts

Re: REST vs GraphQL vs gRPC

#121
post #114

Earlier quoted context omitted.

You don't get much more human readable than GraphQL syntax. There are now oodles of code generation tools available for GraphQL schemas which takes most of the heavy lifting out of the equation.

Do the code generators create efficient relational queries? I don't know about everyone else but my production data is highly relational.

I use gqlgen for a Go backend and the combination of our schema design and the default codegen results in it opening one database connection for every row that ends up in the output. You can manually adjust it to not do that, but it doesn't seem like a good design to me.

(It also does each of these fetches in a separate goroutine, leading me to believe that it's really designed to be a proxy in front of a bunch of microservices, not an API server for a relational database. Even in that case, I'm not convinced it's an entirely perfect design -- for a large resultset you're probably going to pop the circuit breaker on that backend when you make 1000 requests to it in parallel all at the exact same instant. Because our "microservice" was Postgres, we very quickly determined where to set our max database connection limit, because Postgres is particularly picky about not letting you open 1000 connections to it.

I had the pleasure of reading the generated code and noticing the goroutine-per-slice-element design when our code wrapped the entire request in a database transaction. Transactions aren't thread-safe, so multiple goroutines would be consuming the bytes out of the network buffer in parallel, and this resulted in very obvious breakages as the protocol failed to be decoded. Fun stuff! I'll point out that if you are a Go library, you should not assume the code you're calling is thread-safe... but they did the opposite. Random un-asked-for parallelism is why I will always prefer dumb RPCs to a query language on top of a query language. Sometimes you really want to be explicit rather than implicit, even if being explicit is kind of boring.)

Re: REST vs GraphQL vs gRPC

#122
post #15

I think for people who didnt try GRPC yet, this is for me the winner feature: "Generates client and server code in your programming language. This can save engineering time from writing service calling code" It saves around 30% development time on features with lots of API calls. And it grows better since there is a strict contract. Human readability is over-rated for API's.

In my personal experience the other huge benefit is you now have a source of truth for documentation. Since your API definition is code you can leave comments in it and code review it all while having a language that is very approachable for anyone who is familiar with the C family of languages.

For a newcomer having `message Thing {}` and `service ThingChanger {}` is very approachable because it maps directly into the beginner's native programming language. If they started out with Python/C++/Java you can say "It's like a class that lives on another computer" and they instantly get it.

Re: REST vs GraphQL vs gRPC

#123
post #15

I think for people who didnt try GRPC yet, this is for me the winner feature: "Generates client and server code in your programming language. This can save engineering time from writing service calling code" It saves around 30% development time on features with lots of API calls. And it grows better since there is a strict contract. Human readability is over-rated for API's.

On the GraphQL side you can use gqless[0] (or the improved fork I helped sponsor, here[1]). It's by far the best DX I've had for any data fetching library: fully typed calls, no strings at all, no duplication of code or weird importing, no compiler, and it resolves the entire tree and creates a single fetch call.

[0] https://github.com/gqless/gqless

[1] https://github.com/PabloSzx/new_gqless

Re: REST vs GraphQL vs gRPC

#124

No mention of what I see as the biggest con of GraphQL: You must build a lot of rate limiting and security logic, or your APIs are easily abused. A naive GraphQL implementation makes it trivial to fetch giant swaths of your database. That's fine with a 100% trusted client, but if you're using this for a public API or web clients, you can easily be DOSed. Even accidentally! Shopify's API is a pretty good example of th…

I'm a huge fan of GraphQL, and work full-time on a security scanner for GraphQL APIs, but denial of service is a huge (but easily mitigated) risk of GraphQL APIs, simply because of the lack of education and resources surrounding the topic.

One fairly interesting denial of service vector that I've found on nearly every API I've scanned has to do with error messages. Many APIs don't bound the number of error messages that are returned, so you can query for a huge number of fields that aren't in the schema, and then each of those will translate to an error message in the response.

If the server supports fragments, you can also sometimes construct a recursive payload that expands, like the billion laughs attack, into a massive response that can take down the server, or eat up their egress costs.

Re: REST vs GraphQL vs gRPC

#125

No mention of what I see as the biggest con of GraphQL: You must build a lot of rate limiting and security logic, or your APIs are easily abused. A naive GraphQL implementation makes it trivial to fetch giant swaths of your database. That's fine with a 100% trusted client, but if you're using this for a public API or web clients, you can easily be DOSed. Even accidentally! Shopify's API is a pretty good example of th…

I'm not convinced that GraphQL is any more difficult to implement robust rate limiting or other performance guarantees than a REST API with comparable functionality. As soon as you start implementing field/resource customizability in a REST API you have roughly the same problems guaranteeing performance. JSON:API, for example, specifies how to request fields on related objects with a syntax like `/articles/1?include=…

> Of course, if the argument is simply that it tends to be more challenging to manage performance of GraphQL APIs simply because GraphQL APIs tend to offer a lot more functionality than REST APIs, then of course I agree, but that's not a particularly useful observation. Indeed having no API at all would further reduce the challenge!

On their own, such arguments are indeed not useful. But if you can further point out that GraphQL has more functionality than is required, then you can basically make a YAGNI-style argument against GraphQL.

Re: REST vs GraphQL vs gRPC

#126

No mention of what I see as the biggest con of GraphQL: You must build a lot of rate limiting and security logic, or your APIs are easily abused. A naive GraphQL implementation makes it trivial to fetch giant swaths of your database. That's fine with a 100% trusted client, but if you're using this for a public API or web clients, you can easily be DOSed. Even accidentally! Shopify's API is a pretty good example of th…

edges and node come from Relay, not from the core GraphQL spec. They're just one way to do pagination. I like edges and node, it gives you a place to encode information about the relationship between the two objects, if you want to. And if all your endpoints standardize on this Relay pagination, you get standard cursor/offset fetching, along with the option to add relationship metadata in the future if you want, with…

Technically the spec is part of GraphQL itself now, but an optional recommendation, not something you’re obliged to do.

That said, like you I am a fan.

It’s a pretty defensible pattern, more here for those interested: https://andrewingram.net/posts/demystifying-graphql-connecti...

The overall verbosity of a GraphQL queue tends to not be a huge issue either, because in practice individual components are only concerning themselves with small subsets of it (i.e fragments). I’m a firm believer that people will have a better time with GraphQL if they adopt Relay’s bottom-up fragment-oriented pattern, rather than a top-down query-oriented pattern - which you often see in codebases by people who’ve never heard of Relay.

Re: REST vs GraphQL vs gRPC

#127

Earlier quoted context omitted.

Thrift supports many serializations both binary and human readable that you could choose at runtime, say for debugging. I never did use the feature, having got tired of using Thrift for other reasons (e.g. poor interoperability Java/Scala).

Wait, thrift interoperates poorly with Java? We are stuck using it in go because another (Java-heavy) team exposes their data via it, and the experience has been awful even for a simple service. So what is it good in?

This was a long way back. Specifically, the Scrooge (or Finagle) generator for Scala and Java supported different versions of Thrift libraries. Maybe the problem was related to having a project with both Java and Scala and over the wire interop would have been fine--don't remember the exact details.

Re: REST vs GraphQL vs gRPC

#128
post #63
post #33

Earlier quoted context omitted.

Code generation and strong contracts are good (and C#/Java developers have been doing this forever with SOAP/XML), but they do place some serious restrictions on flexibility. I’m not sure how gRPC handles this, but adding an additional field to a SOAP interface meant regenerating code across all the clients else they would fail at runtime while deserializing payloads. A plus for GraphQL is that because each client re…

Learned that at Google, for each service method, introduce individual Request and Response messages, even if you can reuse. This way you can extend without breaking. Also never reuse old/deleted field (number), and be very careful if you change the type (better not).

These were basic principles I put in place at a previous company that had a number of API-only customers. Request/Response messages. Point releases could only contain additive changes. Any changes to existing behaviors, removal of fields, or type changes required incrementing the API version, with support for current and previous major versions.

Re: REST vs GraphQL vs gRPC

#129
post #15

I think for people who didnt try GRPC yet, this is for me the winner feature: "Generates client and server code in your programming language. This can save engineering time from writing service calling code" It saves around 30% development time on features with lots of API calls. And it grows better since there is a strict contract. Human readability is over-rated for API's.

I adore gRPC but figuring out how to use it from browser JavaScript is painful. The official grpc-web [1] client requires envoy on the server which I don't want. The improbable-eng grpc-web [2] implementation has a native Go proxy you can integrate into a server, but seems riddled with caveats and feels a bit immature overall.

Does grpc-web work well? Is there a way to skip the proxy layer and use protobufs directly if you use websockets?

[1]: https://github.com/grpc/grpc-web [2]: https://github.com/grpc/grpc-web

Re: REST vs GraphQL vs gRPC

#130

i don't know about you but in my experience, unless you have Google's size microservices and infrastructure gRPC (with protocol buffers) is just tedious. - need an extra step when doing protoc compilation of your models - cannot easily inspect and debug your messages across your infrastructure without a proper protobuf decoder/encoder If you only have Go microservices talking via RPC there is GOB encoding which is a…

> unless you have Google's size microservices and infrastructure gRPC (with protocol buffers) is just tedious

Having used gRPC in very small teams (> need an extra step when doing protoc compilation of your models

For us this was hidden by our build systems. In one company we used Gradle and then later Bazel. In both you can set it up so you plop a .proto into a folder and everything "works" with autocompletes and all.

> cannot easily inspect and debug your messages across your infrastructure without a proper protobuf decoder/encoder

There's a lot of tooling that has recently been developed that makes all of this much easier.

- https://github.com/fullstorydev/grpcurl

- https://github.com/uw-labs/bloomrpc

- https://kreya.app/

You can also use grpc-web as a reverse proxy to expose normal REST-like endpoints for debugging as well.

> If you talk with other non-Go services then a JSON or XML transport encoding will do the job too (JSON rpc).

The benefit of protos is they're a source of truth across multiple languages/projects with well known ways to maintain backwards comparability.

You can even build tooling to automate very complex things:

- Breaking Change Detector: https://docs.buf.build/breaking-usage/

- Linting (Style Checking): https://docs.buf.build/lint-usage/

There's many more things that can be done but you get the idea.

On top of this you get something else that is way better: Relatively fast server that's configured & interfaces with the same way in every programming language. This has been a massive time sink in the past where you have to investigate nginx/*cgi, sonic/flask/waitress/wsgi, rails, and hundreds of other things for every single language stack each with their own gotchas. gRPC's ecosystem doesn't really have that pain point.

Post reply on HN