4 ms·
> doing things that would be even the simplest of queries becomes a project in writing what are effectively bad performance joins via random http APIs In some
by JMTQp8lwXL 6y ago
> doing things that would be even the simplest of queries becomes a project in writing what are effectively bad performance joins via random http APIs
In some ways, is GraphQL trying to slap a fresh coat of paint on what is otherwise is a bad problem under the hood? At my employer, we're trying to adopt it, but we've never addressed the underlying performance issues of the microservices, and now the slowness is quite apparent with the GraphQL wrapper tier.
This isn't a diss to GraphQL. The queries are awesome to write. The developer experience of writing / being the client of a GraphQL server is extremely excellent. But I feel I might not be alone in a journey that is playing out to be a mediocre implementation because we are avoiding the core problem.
- an_opabinia 6y agoIt does beg the question, if the developer authors a GraphQL server to do joins, why didn't the application just do that in the first place? Is it always a symptom of a dead piece of engineering?
- rienbdj 6y agoThe alternative is an explosion of REST API routes as each application has different requirements. It is much simpler to have one graphql endpoint that is flexible enough for all consumers.
- GordonS 6y agoI've seen the explosion of REST endpoints you mention, several times. But isn't GraphQL just adding a thin veneer over that, giving the appearance of a single URL, but actually kind of containing all those REST routes under the hood? If you have an explosion of REST routes, you'll likely end up with an explosio6of GraphQL queries too.
- valenterry 6y agoNo. It contains only a subset of the rest routes and allows to combine them efficiently. That is what avoids the explosion. You don't have to add any new "rest route" equivalent in graphQL if some user just wants a new combination of data but doesn't want to make 10 requests to get it.
- GordonS 6y agoThat's the theory. But I've only seen it work in practice if there is a single backend data source, and that data source is a database. In which case, we've been able to achieve similar results using OData for several years. Often in reality, you end up with specialised GraphQL queries for performance reasons, because they are reading and combining data from a plethora of backend data sources - cloud-based APIs, on-premise APIs, external APIs, databases...
- valenterry 6y agoThat's the theory and it can very well be practice. It has worked very well for the teams where I used it or have seen it being used. And I'm talking about a service that provides an API to a frontend (or other backend services) and aggregating data from multiple datasources of different kinds into one graphQL API. > Often in reality, you end up with specialised GraphQL queries for performance reasons Ah, is that so? And with REST you don't? You seem to have _a lot_ of experience with GraphQL. I wonder why your previous post has the form of a question. Or was that just a sneaky way of giving your opinion without backing it up?
- GordonS 6y ago> Ah, is that so? And with REST you don't? No, that's exactly what you end up with using REST; I'm pointing out that, at least with deployments I've seen, GraphQL ends up with the same problems, only hidden behind a single URL. > You seem to have _a lot_ of experience with GraphQL I didn't (and wouldn't) say that I have a lot of experience with GraphQL (I have far more with REST/HTTP-based APIs), but I've seen it used enough times to know it's not a panacea, and doesn't always solve the expected problems, especially when it's fronting dozens of (sometimes painfully slow) backend data sources. > I wonder why your previous post has the form of a question It doesn't? I was proffering an opinion, based on my observations when GraphQL is fronting many data sources. > Or was that just a sneaky way of giving your opinion without backing it up? I would politely and respectfully point you towards HN's comment guidelines[0] [0] https://news.ycombinator.com/newsguidelines.html#comments https://news.ycombinator.com/newsguidelines.html#comments
- Skgqie1 6y agoYup, pretty much. However, the implications of veneer can be significant. Providing a single unified interface which provides granular, unified querying of disparate types has several benefits. In particular, it can simplify logic in the consuming application, and reduce network load (both in terms of the number of requests, and especially in the amount of data returned). For example, a pet website backed by a traditional REST architecture, may have separate endpoints for say `/pets`, `/owners`, and `/purchases `. In this context, the front-end may need to make calls to all three of these endpoints, retrieving the full payload for each - only to discard most of the fields, and keep 2 or 3 relevant ones from each entity. By comparisons, a GraphQL based approach would allow a single consolidate query for just those specific fields (from all entities). Of course this isn't relevant in every use case, and there's no silver bullet - and in many cases, a REST based approach may well be better.
- jonathanlydall 6y agoIt's essentially a facade pattern[0], which in itself can be a good thing. For example, if all consumers move to GraphQL and away from interacting with all the separate microservice REST endpoints individually, you then have the option of refactoring your architecture (merging/adding micrososervices for example) without worrying about disrupting consumers so long as you ensure that the GraphQL queries still works. [0]: https://en.wikipedia.org/wiki/Facade_pattern https://en.wikipedia.org/wiki/Facade_pattern
- sixdimensional 6y agoLook into the patterns of CQRS, event sourcing, flow based programming and materialized views. GraphQL is an interface layer, but you still have to solve for the layer below. API composition only works when the network boundary and services are performance compatible to federate queries. The patterns above can be used to work around the performance concern at a cost of system complexity.
- rualca 6y ago> API composition only works when the network boundary and services are performance compatible to federate queries. Isn't that the whole point? The main reason why individual reaponsibilities are peeled out of a monolithic service into independent services is to be able to unload those requests to services that can be scaled independently.
- konschubert 6y agoIf you find yourself doing in-code joins across microservices, you need to stop and think: Are my services correctly scoped? Am I doing these joins because there is maybe a higher level domain that goes across these two services? Should I re-scope my services? Or should I build an Aggregator-View service that holds a JOINED copy of the data. These aggregator-view services often make sense as Backend-For-Frontends. They must be restricted to a read-only API since they mirror data from other microservices. GraphQL is a dead end when you are doing joins in code.
- tpetry 6y agoWhat you are describing is in my optinion the exact problem happening with almost all microservices. Building an aggregator microservice to join together two services is another microservice in a complex microservice landscape... People on hn seem to hate monoliths, but a monolith with just a few services outsourced to microservices is much easier to handle. No more joining microservice, no more race conditions when trying to do transactional processing over some microservices and all the problems of microservices.
- konschubert 6y agoI agree that a well-maintained monolith is simpler and more stable than micro services. The emphasis is on well-maintained. If you’ve ever had team A write a crazy query and kill the database for team B, you’ll start to appreciate the damage containment and encapsulation that microservices provide. EDIT: Of course there might be other, better solutions to this problem.
- konschubert 6y agoWith “kill the database” I mean things such as transaction deadlocks.
- fatnoah 6y ago>If you find yourself doing in-code joins across microservices, you need to stop and think: This is a place where far too few people stop to think about what you're doing. I've seen too many cases where an operation requires coordinating requests across multiple service methods THAT ARE ONLY USED IN THAT PARTICULAR OPERATION! The devs spend all of their time a) coordinating things and b) trying to make it performant and c) realizing none of the gains of having microservices to begin with.