GraphQL: Highway for a Distributed Monolith?

GraphQL makes a lot of sense for mobile applications. Especially when we consider poor networks. Aggregating data in one call is very powerful and makes a lot of sense for mobile. GraphQL allows a single interface for all operations for reads and writes. GraphQL is not that different from an API gateway or aggregation service. Selecting only the fields you need allows you to reduce the payload of requests, and latency resulting in improvements in the user experience via the mobile app. GraphQL has a lot of power and flexibility, which requires lots of attention to detail as well. Understanding the tradeoffs is important, one thing you are giving away by using only GraphQL is the ability to make multiple service calls in an asynchronous fashion, GraphQL is synchronous. GraphQL performance will have penalties. GraphQL never will be as fast as a modular monolith doing proper queries in the database. We can mitigate some performance issues by doing pre-loading, batching, or just caching queries. Besides the tradeoffs, let's take a look at some design decisions that can increase or decrease isolation. Distributed Monoliths are everywhere. It is not hard to leak abstractions and hurt isolation

Direct Database Access 

GraphQL provides a layer of indirection. Due to the resolvers, we can add code that transforms the internal service model to the GraphQL schema. However, if we dont pay attention, we can easily have GraphQL calling databases directly.

GraphQL Database Access

When there is direct database access we are bypassing the service interface. When a table/column changes, there will be impact on the GraphQL component. Database concerns can easily leak to the graphQL schema which easily can be just a poor reflection of all databases. We can improve such a situation by adding services.

Enter Services

Calling service interfaces is great. We abstract the service implementation details such as languages internal persistence models and datastore technologies. By introducing services we make GraphQL more stable as not all database changes will impact the service contract. 

GraphQL Calling Services

However, by doing so, we have another level of indirection. Which is not bad and should exist anyway besides the GraphQL use cases. It is not impossible that the services will introduce breaking changes and be out of sync with GraphQL. To fix this sync problem is very common to see javascript/typescript solutions (like tRPC), often running in NodeJS trying to have the same language on the backend and front to avoid this issue. The penalty is performance and coupling.

Unfortunately, there is a second problem here. Cross-domain access. One thing is the UI across multiple domains, and the other thing is services calling GraphQL to access cross-domain data. Such a situation can lead to high coupling and unwanted comunication coupling.  

GraphQL per Domains

Business domains should be isolated. It's natural to have web applications and mobile applications with cross-domain features. Even so, you have some use cases, let's say you have 3 use cases for cross-domain access, it is still a good idea to isolate these use cases and not mix them with other domains by ancient. 


GraphQL per Domains

PII is sensitive data by nature. You want to control the systems that have access instead of having the convenience of any service or application consuming freely. PII requires encryption and sharing keys, which have security concerns and other challenges like compensating controls, catalogs, access logs, and key rotations. 

Different countries and different industries have different requirements and compliances around PII, if you design from scratch is a good idea to isolate it. You can still expose it via GraphQL but it should be on the different GraphQL. Now can have tight control over who calls it and avoid reuse-by-accident. Netflix recently shared its experiences with the federation, GraphQL, and migrations. Uber also shared experiences on introducing gateways between groups of services and not allowing comunication without going through the gateway in the famous DOMA article.

Distributed Monoliths are real, we need to start paying attention to these details. GraphQL is a powerful technology that should be leveraged but paying attention to the details to avoid bigger issues. GraphQL is a powerful tool and makes sense for mobile applications. GraphQL is not the only way and far is the most efficient, it is fine to use GraphQL but you need to pay attention to the small details in order to avoid bigger problems. Convenience has a price that sometimes is too high. 

Cheers,
Diego Pacheco

Popular posts from this blog

Kafka Streams with Java 15

Rust and Java Interoperability

HMAC in Java