Why I struggle with GraphQL

And my take on where it makes sense

Tim Meeuwissen
6 min readMar 20, 2020

--

First, some definitions. “GraphQL” itself, literally stands for “Graph Query Language”. It is not a tangible system itself. It defines a method of talking (language) to ask specific data (query) from a network of data nodes that are interconnected with each other (query).

The implementation of that language shouldn’t matter.

The analogy here is like saying; no matter your nationality, you can learn english. It doesn’t change a bit about the english language that you’ve started speaking it, and the language doesn’t change a bit that you use her to communicate with.

However, there are ways to start working with GraphQL that make a lot of sense. Pre-packaged, easy to start with. One of them is Apollo running on node. But you can be free to implement your own if you’d like.

A real solution for DDD

When you’ve scaled up your organisation and served you right, your systems started fragmenting. A natural way with the current technology to fragment your digital solution is by dividing it into services.

Domain Driven Design (DDD) helps defining what should be in these services. You can split functionality in arbitrary ways over services, but ideally you’d like to segment the functionality in logical clusters. When you cluster the logic per business domain, life becomes a lot easier, because responsibility for them and what their contents is can way more easily be shared with your business stakeholders.

But there’s a cost to this seemingly super-logical way of working. You’ll go (no shortage of science based acronyms around the CAP theorem). Where state was once managed in a single database, the logic, as well as the state is now scattered all over the landscape, over several services. You’ll need a way to combine that data in an easy way. GraphQL to the rescue.

Hero complex

Have you ever heard of the hero complex? Fixing problems feels good. It makes you feel important. But when you fix it permanently and structurally, there’s a risk you can’t be the hero anymore. You are certain you are the here now, because you know this domain. But it’s not certain you will be the hero of the next problem and that’s scary and makes you feel irrelevant. It’s the firefighter starting the fires. It happens more than you might think.

I tell you this, because GraphQL is really prone to being the hero in situations where it shouldn’t. It tends to temper fires, where they should actually be extinguished.

Before you know it, it solves all kinds of issues of the landscape behind it. Like authorisation, , transforming, combining, aggregating. It’s so easy to do it there, since it’s one place to fix for all systems behind it. The pain of each domain bleeds to this central bus and we now only have to do a bandaid on one spot which feels quicker and easier. No brainer right? Right…

But let’s just say we swear we won’t do all that. We won’t implement all this goodness in this sweet spot. Life’s good isn’t it?

The struggle is real

So on the one hand I adore the fact that you can query your service landscape as if it where one database. It removes the tedious implementations of fetching data from multiple services in all data consuming spots of your solution.

On the other hand it forms the next bottleneck in your landscape. Before you know it, responsibilities belonging to their respected domains move towards this central spot. With each addition of a service in the back, the consuming parties will have to wait until it’s added to the central query service.

This is killing responsibility and creating a single point of failure where there doesn’t have to be one. Unless it’s automated and orchestrated without intervention of a human of course. I haven’t yet seen such a solution though. Combining data rarely goes without intervention, especially when there’s so much riding on it.

Progressive new insights in data structures, how data is combinable and which version of an endpoint should be used are adding to the pain of pulling all data through this hotspot. You now have to consider all consuming parties when you need to change this logic. It just doesn’t make sense to position it centrally in your landscape.

Okay enough already!

If there’s one thing that I don’t like, it’s having a negative mindset. You simply can’t say something is wrong, unless you have a solution on how to do it better, and contribute to a solution.

In case you have the situation that I describe above: no worries! It led you to where you are today, but I hope it brings some insights in why it’s relevant to improve from there.

Never resent what you have today, since it brought you there to begin with. Just analyse it carefully and don’t settle for mediocre. It will show you where you need to go to, in order to become better.

Yay I just quoted myself right there :D

So where does it fit?

I think a GraphQL enabled service endpoints offer a great way for external partners to query your landscape, without having to know all the intricate details. You can then version that endpoint like all other endpoints, and carefully publish documentation. You won’t have to change it that often, and the teams that are responsible for public API’s can own the connection and implementation here. The pace is low, and this team won’t block any development between backend services as well as frontend development / consumption of these services.

And what about where it does not fit?

I would expose a library which all frontend development could leverage. This library would consist out of many individual components, managed in their own repository by the team that’s responsible for the backend as well. Your CI/CD and test frameworks should trip whenever regression occurs or incompatibility is introduced, like it should for all changes of dependencies.

This way, the frontend can call functions that 1–1 provide an interface to the service, or convenience functions that combine data from multiple services right there in the code. The ownership of the combining functions lays at the biggest domain (hierarchically highest entity). Since the higher entity requires the smaller entity, and the other way around isn’t necessarily the case.

That layer should take care of handling requests in parallel and in the right order.

But… That’s exactly what GraphQL solutions do for you

I know I know. And that’s great! As long as you don’t do it over the same service like you do for all of the other requests, and the person that works on the frontend isn’t dependant on the person that combines stuff to talk with a service another person has made in the backend, it’s good!

Where the implementation is done — and only on that spot — you should be able to tailor and deviate from fixed ways to combine data as the developer / application sees fit. And while doing it, remain the most pure form of transparency on which backend logic you actually use to achieve that.

I know that I’m covering a controversial topic. And like I wrote, I struggle with this myself as well. Context is also key here. The size of the project and the complexity of the service landscape evidently matters and I didn’t take that context into consideration writing this post. But I do feel it’s something to talk about. Perhaps you might have some valuable insights that make me think otherwise :-). I’d love to hear about them!

--

--

Tim Meeuwissen
Tim Meeuwissen

Written by Tim Meeuwissen

Seriously passionate in understanding how stuff works

No responses yet