Remix.run Logo
jensneuse 4 days ago

I'm with WunderGraph, a vendor providing enterprise tooling for GraphQL.

First, I absolutely love Capn Proto and the ideas of chaining calls on objects. It's amazing to see what's possible with CapNweb.

However, one of the examples compares it to GraphQL, which I think falls a bit short of how enterprises use the Query language in real life.

First, like others mentioned, you'll have N+1 problems for nested lists. That is, if we call comments() on each post and author() on each comment, we absolutely don't want to have one individual call per nested object. In GraphQL, with the data loader pattern, this is just 3 calls.

Second, there's also an element of security. Advanced GraphQL gateways like WunderGraph's are capable of implementing fine grained rate limiting that prevent a client to ask for too much data. With this RPC object calling style, we don't have a notion of "Query Plans", so we cannot statically analyze a combination of API calls and estimate the cost before executing them.

Lastly, GraphQL these days is mostly used with Federation. That means a single client talks to a Gateway (e.g. WunderGraph's Cosmo Router) and the Router distributed the calls efficiently across many sub services (Subgraphs) with a query planner that finds the optimal way to load information from multiple services. While capNweb looks amazing, the reality is that a client would have to talk to many services.

Which brings me to my last point. Instead of Going the capNweb vs GraphQL route, I'd think more about how the two can work together. What if a client could use CapNweb to talk to a Federation Router that allows it to interact with entities, the object definitions in a GraphQL Federation system.

I think this is really worth exploring. Not going against other API styles but trying to combine the strengths.

- https://wundergraph.com/

rhaps0dy 3 days ago | parent | next [-]

> First, like others mentioned, you'll have N+1 problems for nested lists. That is, if we call comments() on each post and author() on each comment, we absolutely don't want to have one individual call per nested object. In GraphQL, with the data loader pattern, this is just 3 calls.

Why is that a problem? As far as I can tell, those calls are all done on the server, where they're cheap normal function calls, and the results are all sent back with 1 roundtrip; because of the pipelining.

robmccoll 3 days ago | parent [-]

Because they each result in round-trips and individual queries to the database rather than a more efficient single round-trip with a join. Note: I don't know the details of GraphQL, but I'm assuming it does the smarter thing.

In this paradigm, the places where you are calling map() could probably be replaced with explicit getComments() or getCommentsWithAuthors() or two methods that do just one query each.

kentonv 3 days ago | parent [-]

Well, if the server is a Cloudflare Durable Object running sqlite, then the round-trip to the database is free.

https://www.sqlite.org/np1queryprob.html

But you are right that this won't work great with traditional databases without significantly more magic on the server side, and in that sense the comparison with GraphQL is... aggressive :)

It is still much better than making all the calls client-side, of course. And there are many use cases where you're not querying a database.

And maybe there can be some fusion between GraphQL server infrastructure and this RPC-oriented syntax that gives people the best of both worlds?

jensneuse 4 days ago | parent | prev [-]

Side note, a lot of people these days build agents on top of APIs. GraphQL has selection sets, which allows you to select subsets of objects. This is quite handy when it comes to gents because of context window limitations.