Rejoiner: Unified GraphQL schema from gRPC microservices
github.com
github.com
We found that we could get the same benefits (minus the performance of gRPC) by just using GraphQL for all of our microservices, and dynamically stitching them together with Apollo’s graphql-tools[1].
We’re really high on the approach because it lets us develop independent services, each with a strongly typed interface, and then mix and match them into a single GraphQL interface on the fly.
It’s been gaining a lot of traction internally at my company. We even put together a “create-react-app” for GraphQL so our teams can easily spin up new services.
[1] https://www.apollographql.com/docs/graphql-tools/schema-stit...
You can just treat it as a realitvely flat, rest-like schema that does not have much in terms of graph relations.
The Graph in GraphQL is mostly optional.
If you define your methods and types independently of each other (i.e. without any sort of graph or relationship) I don’t see how it’s any different than SOAP/XML or gRPC.
The bonus comes with graph/query capabilities that come layered on top. We’re basically exposing our canonical domain model (broken down into microservices by bounded context, and stitched back together to present a unified model), and at the same time, we should have no problem handling more RPC styled requests (e.g. sendNotificationEmail()) when necessary.
This approach was a bit of a revelation for us, but we haven’t really seen anyone else out there doing the same thing, so I hope we aren’t barking up the wrong tree.
GraphQL is amazing when your service has to respond to unpredictable queries, like with a public API. But if the queries can be predicted, like in-between services, you lose a lot of database performance by opening your service up to literally any query pattern imaginable. Specifically; nested graphql queries traveling along edges of your data graph will inevitably span multiple tables, but actually implementing it with a single database join is practically difficult, if not impossible in many cases.
GraphQL also doesn't play well with strongly typed languages. Its completely fundamental to how GraphQL works. Your best, safest bet is to have pre-written queries with types associated with those queries, but at that point its questionable exactly what benefit you're getting from GraphQL.
There are practically no mature GraphQL frameworks out there. In practice, Apollo is pretty good, though its incredible to me that you're already using schema-stitching in a production app when it was released just a month or two ago. We're not about to force services to adopt Node just for Apollo. There are a few other promising GraphQL servers in other languages, but none are at the point where they feel production hardened.
I agree that you have to be careful when it comes to performance, but ultimately, that has to be balanced with the needs of the internal environment. One-off RPC interfaces are easy to set up between systems, but can lack the flexibility to adapt to the requirements of unknown future consumers (I'm thinking large enterprise with multiple lines-of-business). This can lead to a lot of rework and regression testing in the best case, or multiple copy/paste variations with minor differences in the worst.
>GraphQL also doesn't play well with strongly typed languages. Its completely fundamental to how GraphQL works. Your best, safest bet is to have pre-written queries with types associated with those queries, but at that point its questionable exactly what benefit you're getting from GraphQL.
I'm not sure I follow you here. GraphQL's schema definition and introspection capabilities are very similar to SOAP/XML and WSDL's, and those play very well with typed languages. Its possible to generate type definitions off the GraphQL schemas to use on the server side to ensure compile time safety, and there are multiple libraries that will do the same on the client side. [1][2][3] As for the benefit, flexibility of consumption. Again, I'm thinking enterprise scale where services have long lifespans, and the consumers aren't always known in advance.
>its incredible to me that you're already using schema-stitching in a production app when it was released just a month or two ago
Nothing in production yet. An approach like this will definitely have to be vetted more thoroughly before it gets to that point.
>We're not about to force services to adopt Node just for Apollo
Only required for the schema-stitching layer. The individual GraphQL services can be developed with any language/platform that has an implementation.
[1]https://github.com/avantcredit/gql2ts [2]https://github.com/apollographql/apollo-codegen [3]https://github.com/Shopify/graphql_java_gen
I still feel like we are way ahead with the concepts in (shameless plug alert) https://github.com/1backend/1backend when it comes to the big picture of building microservices that actually build on each other, although it's statistically very likely this is just a personal opinion :)).
Anyway, I'm generally happy that this space is advancing, as someone who spent most of his recent career in this space I almost gave up hope: simply there was not even a common vocabulary to properly discuss ideas, everybody just wanted microservices because that was the next cool thing, and looked absolutely perplexed when explained the pitfalls.
GraphQL, this, and all the different kind of faas platforms popping up nowadays all help as a point of reference.
I truly think we are on the verge of radically changing how we build applications soon - I think these technologies can be viewed as a new breed of web frameworks, a breed which has the distributed principles in its core.
This library solves a specific problem at the query layer. It's definitely time we had something like this across microservices and functions. There have been other attempts but in unstructured ways.
It's likely in the long term systems architectures are multilayered. Monoliths, microservices and functions along with graphql or other query models all within the same environment.
Usually what happens is that they try a complete rewrite which turns out to be rather expensive (especially in opportunity cost). They should ideally just move the pain points (ie. performance problems) to services and optimize that, but the enthusiasm towards the shiny new way of doing things that will fix their problems is so high that they opt for the riskier move of rewriting all the things.
That scenario is simply so dangerous and expensive that companies will be better off starting with a proper distributed framework - which doesn't really exists yet, but we are slowly getting there.
Anyway, this is just my 2c but I have seen this pattern of full blown rewrite at a lot of places.
When you start to breakdown the monolith you may end up with 10 services all using different databases, message queues and message formats. Going the whole rewrite approach usually involves defining an architecture and single uniform approach to development which eventually leads to higher productivity since it eliminates choice and lets you focus on the important tasks.
I do however agree that not everyone who does it needs to.
We've had to drop gRPC as a direct result of this.
Code is open source, fork and then submit a PR?
I theory yes, but would you want to? In my experience I've found that building REST services is very different than building a GRPC service. The contract between the client and server are totally different.
> gRPC is no use for a large number of use cases. Shame really since it has promise but still seems half-baked.
gRPC is half-baked? You realize that the a large portion of the google backend is built on top of gRPC. Its an extremely well tested tool.
I am aware Google use gRPC in their SDKs and backends, none of which are JS web.
So yes, I want to build microservices with gRPC but expose them with REST for legacy/external clients.
It's browsers in this case that are the laggard (trailers have been part of the spec since HTTP/1.1).
As a proponent of gRPC, I can say that some of the libraries, tools, docs, etc. are definitely half-baked. There are plenty of severe issues in the (confusing codebase of) grpc-go that have been open for over 1.5y.