ramoska blog logo showing grasshoper

ramoska

Why use GraphQL?

Posted on January 2024 in Web Development

How did I get here?

Me and my team are about to start a new project. It will be a Symfony project exposing API to be used internally by our other projects. There's a slight possibility that it will be exposed to be used by third parties (our clients), but that is not the main concern right now. When we started discussing the architecture of the project, we saw that 3 of us had 3 different opinions on how the API should be exposed. And when looking at the use cases, to me it looked like the best solution would be to use GraphQL, other alternatives being REST and (g)RPC. The API doesn't fit the REST model very well, and I would be more than happy to use gRPC. But why I'm sticking with GraphQL? Let's see.

Why GraphQL?

Advantages over REST

As I mentioned before, the API doesn't fit the REST model very well - it's not a CRUD API. And even if it was, you always run into situations where simple POST request is not enough, because you are dealing with a complex business logic. Let's imagine you're dealing with orders and need to ship them. All sounds pretty simple. You have something like /orders/{id}/shipments endpoint, make POST request to send order to buyer and that's it. But what if you now have to consolidate shipments? You need to send multiple orders to the same buyer. How your payload will look like? And cases like this happen all the time. That's why I'm not a big fan of REST as a go to solution for APIs. And also this time it is also not a good fit. What REST API usually does have that I really like is having pretty clear dependencies between resources. Can it get any clearer than /orders/{id}/fulfillments or /users/{userId}/orders/{orderId}/items? But GraphQL allows us to have even clearer dependency tree. And that is achieved by types and relations between them. And then we have all that querying power that REST APIs simply are not capable of.

Advantages over (g)RPC

This one is a bit more nuanced. IMO gRPC is a great tool to communicate between internal APIs. It is fast, has low overhead and is (mostly) easy to use. Unless computers is not your main (or even side) business. Then you have to deal with all the protobuf stuff when you're very comfortable with JSON APIs (mostly REST). And that's not a big deal, but it's still something you have to learn. And as I mentioned, API we'll be building has a slight possibility of being exposed to third parties. And that's where gRPC falls short. And GraphQL at the end of the day is your regular JSON API that needs no binary encoding.

Other types of RPC APIs is also not a great fit. First of all saying that they are not popular is very generous. And secondly, they are not very flexible. For actions (or commands) that might be sufficient, but for queries it's not. At least in comparison to GraphQL. Also you need to document it. We're using API Platform to expose our APIs (and most likely will be using it for this one also) that helps with documentation a lot. But my gut feeling is that document REST API or GraphQL API is easier than document RPC API, even though most likely these differences are not that big. Nonetheless, GraphQL still works as RPC API with its mutations, because in essence a mutation is a command to take some action. Going with the same shipping example like before, you can have a mutation shipOrder that takes input of type defined in schema and voila, you have your RPC API. And with better querying capabilities. Again.

Other advantages

One more thing specific to our use case and out organization is that we're already using GraphQL in our other project, so it's not something new or foreign to us. Also since we're in early stages and don't have full picture of the API or the business logic, GraphQL allows us to be very flexible and move forward without worrying too much about the future requirements. Also our go to tool for exposing APIs is API Platform and it already has GraphQL support without much effort. Also because GraphQL comes with a schema, it is very easy to play with it in the browser with GraphiQL. It's not something really big, but still a nice touch.

Reservations about GraphQL

Until now all I did was praise GraphQL. But as I mentioned in the beginning, I have some strong reservations about it. What I'm concerned the most is that it allows to query the API in any way you want. And that's where you have to be very careful not to DoS yourself. Because you for some reason allowed clients to query every single order with its fulfillments, including warehouse details these fulfillments were made, and (for fun) also include all the items in these warehouses. Because why not? API allows you to make such query. That's why I like how Shopify handles it by having leaky bucket and query complexity limits.

Also caching is not something that you have out of the box with GraphQL. There are some strategies to deal with it, but it's like with regex - if you have a problem a decide to solve it with regex, now you have two problems.

Epilogue

After all that I wrote about GraphQL, I think that it is the best approach for my team's use case. It has very flexible querying capabilities, it doesn't have REST API's shortcomings when dealing with complex business logic and can be seen as poor man's RPC API. Also we need to be careful not to shoot ourselves in the foot with allowing clients to run very expensive queries, but I guess it is with most of the APIs (except maybe RPCs).

Tags: API, GraphQL, REST, RPC, PHP, Symfony