Microservices architectures are complex. In part, this is because of the increased number of integration points that you have to take care of. You can leverage the power of GraphQL to create a much simpler architecture that still achieves many of the advantages of a microservices architecture. In this post I describe how you can do that to build a microservices architecture that is easier to understand.
Problems with microservices
Imagine the following architecture:
This is a relatively concise architecture still, but in the real world you'll see these become way more complex. Especially the relationships between services is hard to keep track of. In general the architecture of a system consisting of microservices looks more like a web made by a drunken spider.
So how do you change your service without breaking other services? How do other services handle downtime of your service? How do you make sure requests don't take forever?
You can find answers to these questions. But only by adding more complexity to your already complex system. It is often quite hard to determine who depends on your service, because those dependencies are rarely made explicit.
How GraphQL solves those
The following architecture achieves the same things, but is much simpler:
Leaving out the details, the GraphQL schema for this application could look something like this:
type Order {
customer: Customer!
coupon: Coupon
...
}
The schema makes explicit which dependencies are required and which are optional. When requesting an order, you might not get back a coupon. In case the coupon service is down, popular GraphQL servers (like apollo-server) will catch that and still return the order. It will be able to indicate that it was unable to retrieve the coupon. Most implementations have this kind of degraded service built-in.
As an added benefit, with this schema you immediately document the types of all possible responses. This would be way harder to do if you access multiple microservices directly or through a proxy. That's because if the schema of the coupon service changes, that also needs to be reflected in the schema of the order service.
GraphQL can do smart things to improve performance. For example by adding caching and memoization easily, but also by running resolvers in parallel. You can also do this in every service separately, but that's just more work.
In the classic setup, if you change the customer service, you will need to change both the direct consumers, but also the order service as it is a dependency. With a more complex architecture this quickly gets out of control.
By introducing GraphQL for the integration of all services, the microservice is really only responsible for one thing. It does not need to know how to interact with other services. It does not need to know where to find other services. It just needs to know how to do its own thing, whether that is retrieving orders or managing customer data.
Top comments (1)
nice article, thank you. here is the some example code, I've used graphql as api gateway.
github.com/gungorugur/graphql-bff