Hacker Newsnew | past | comments | ask | show | jobs | submit | jensneuse's commentslogin

The problem with this article is that GraphQL has become much more an enterprise solution over the last few years than a non enterprise one. Even though the general public opinion of X and HN seems to be that GraphQL has negative ROI, it's actually growing strongly in the enterprise API management segment.

GraphQL, in combination with GraphQL has become the new standard for orchestrating Microservices APIs and the development of AI and LLMs gives it even another push as MCP is just another BFF and that's the sweet spot of GraphQL.

Side note, I'm not even defending GraphQL here, it's just about facts if we're looking at who's using and adopting GraphQL. If you look around, from Meta to Airbnb, Uber, Reddit or Booking.com, Atlassian or Monday, GitHub or Gitlab, all these services use GraphQL successfully and these days, banks are adopting it to modernize API access to their Mainframe, SOAP and proprietary RPC APIs.

How do I know you might say? I'm working with WunderGraph (https://wundergraph.com/), one of the most innovative vendors in the market and we're talking to enterprise every day. We've just came home from API days Paris and besides AI and LLMs, everyone in the enterprise is talking about API design, governance and collaboration, which is where GraphQL Federation is very strong and the ecosystem is very mature.

Posts like this are super harmful for the API ecosystem because they come from inexperience and lack of knowledge.

GraphQL can solve over fetching but that's not the reason why enterprises adopt it. GraphQL Federation solves a people problem, not a technical one. It helps orgs scale and govern APIs across a large number of teams and services.

Just recently there was a post here on HN about the problems with dependencies between Microservices, a problem that GraphQL Federation solves very elegantly with the @requires directive.

One thing I've learned over the years is that people who complain about GraphQL are typically not working in the enterprise, and those who use the query language successfully don't usually post on social media about it. It's a tool in the API tool belt besides others like Open API and Kafka. Just go to an API conference and ask what people use.


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/


> 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.


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.


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?


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.


Could I use this to iterate over my AI generated code until it's not detectable anymore? So essentially the moment you publish this tool it stops working?


This is essentially the adversarial generator/discriminator set-up that GANs use.


I'm sure you can but there isn't really an adversarial motive for doing that, I would think :)


Sure there is.


This is what GraphQL was designed for. Only select fields you really need. We've built an OSS Gateway that turns a collection of GraphQL queries into an MCP server to make this simple: https://wundergraph.com/mcp-gateway


The way we've solved this in our MCP gateway (OSS) is that the user first needs to authenticate against our gateway, e.g. by creating a valid JWT with their identity provider, which will be validated using JWKS. Now when they use a tool, they must send their JWT, so the LLM always acts in their behalf. This supports multiple tenants out of the box. (https://wundergraph.com/mcp-gateway)


I think they removed arenas again.


You can often fool yourself by using sync.Pool. pprof looks great because no allocs in benchmarks but memory usage goes through the roof. It's important to measure real world benefits, if any, and not just synthetic benchmarks.


Why would Pool increase memory usage?


Let's say you have constantly 1k requests per second and for each request, you need one buffer, each 1 MiB. That means you have 1 GiB in the pool. Without a pool, there's a high likelihood that you're using less. Why? Because in reality, most requests need a 1 MiB buffer but SOME require a 5 MiB buffer. As such, your pool grows over time as you don't have control over the distribution of the size of the pool items.

So, if you have predictable object sizes, the pool will stay flat. If the workloads are random, you have a new problem because, like in this scenario, your pool grows 5x more.

You can solve this problem. E.g. you can only give back items into the pool that are small enough. Alternatively, you could have a small pool and a big pool, but now you're playing cat and mouse.

In such a scenario, it could also work to simply allocate and use GC to clean up. Then you don't have to worry about memory and the lifetime of objects, which makes your code much simpler to read and reason about.


Long before sync.Pool was a thing, I wrote a pool for []bytes: https://github.com/thejerf/gomempool I haven't taken it down because it isn't obsoleted by sync.Pool because the pool is aware of the size of the []bytes. Though it may be somewhat obsoleted by the fact the GC has gotten a lot better since I wrote it, somewhere in the 1.3 time frame. But it solve exactly that problem I had; relatively infrequent messages from the computer's point of view (e.g., a system that is probably getting messages every 50ms or so), but that had to be pulled into buffers completely to process, and had highly irregular sizes. The GC was doing a ton of work when I was allocating them all the time but it was easy to reuse buffers in my situation.


>That means you have 1 GiB in the pool.

This only happen when every request last 1 second.


I guess if you allocate more than you need upfront that it could increase memory usage.


I don't get it. The pool uses weak pointers under the hood right? If you allocate too much up front, the stuff you don't need will get garbage collected. It's no worse than doing the same without a pool, right?


What the top commenter probably failed to mention, and jensneuse tried to explain is that sync.Pool makes an assumption that the size cost of pooled items are similar. If you are pooling buffers (eg: []byte) or any other type with backing memory which during use can/will grow beyond their initial capacity, can lead to a scenario where backing arrays which have grown to MB capacities are returned by the pool to be used for a few KB, and the KB buffers are returned to high memory jobs which in turn grow the backing arrays to MB and return to the pool.

If that's the case, it's usually better to have non-global pools, pool ranges, drop things after a certain capacity, etc.:

https://github.com/golang/go/issues/23199 https://github.com/golang/go/blob/7e394a2/src/net/http/h2_bu...


also no one GCs sync.Pool. After a spike in utilization, live with increased memory usage until program restart.


That's just not true. Pool contents are GCed after two cycles if unused.


What do you mean? Pool content can't be GCed , because there are references to it: pool itself.

What people do is what this article suggested, pool.Get/pool.Put, which makes it only grow in size even if load profile changes. App literally accumulated now unwanted garbage in pool and no app I have seen made and attempt to GC it.


From the sync.Pool documentation:

> If the Pool holds the only reference when this happens, the item might be deallocated.

Conceptually, the pool is holding a weak pointer to the items inside it. The GC is free to clean them up if it wants to, when it gets triggered.


sync.Pool uses weak references for this purpose. The pool does delay GC, and if your pooled objects have pointers, those are real and can be a problem. If your app never decreases the pool size, you've probably reached a stable equilibrium with usage, or your usage fits a pattern that GC has trouble with. If Go truly cannot GC your pooled objects, you probably have a memory leak. E.g. if you have Nodes in a graph with pointers to each other in the pool, and some root pointer to anything in the pool, that's a memory leak



Is this a modern version of CGI with process isolation?


It's rather something that sits between WebAssembly and containers, combining the sandboxing guarantees of the former with the performance of the latter. From a security perspective, the composition is also really good (WebAssembly enforces memory limits, but doesn't have memory protection, NULL pointers are writable, etc. and this is solved here). But unlike WebAssembly, it is Linux-only. So, not something that can run in Web browsers.


We wrote a breadth first algorithm to handle the second problem you're describing. I'm curious to hear your thought on it: https://wundergraph.com/blog/dataloader_3_0_breadth_first_da...


That's really clever! Kudos. I'm gonna set aside some time this week to dive into the implementation


Short answer:

gRPC is widely understood as an API tool for Microservices. Microservices solve an organizational problem, not a technical one. Ironically, gRPC doesn't really help to solve the organizational problem.

However, GraphQL in combination with Federation, also known as GraphQL Federation actually DOES help organizations to scale APIs across teams and services.

So, even though the typical popular opinion suggests that gRPC is better for Microservices than GraphQL, the reality looks different.


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

Search: