Forget about the BEST, go for what you NEED
At the end of February, I had a workshop about APIs for dotnetdays conference. This was not my first time speaking at this conference and because I had a very good time at last year’s edition, I happily prepared a half-day workshop for the community this year also.
The subject discussed was related to APIs, to be more precise, the never-ending “battle” between REST and GraphQL, how and if they can be compared, if and how is one better than the other and how and when we can transition from REST to GraphQL.
Of course, the discussion can go for hours with pros and cons but my purpose was not to convert anyone to a specific way of doing. Following, I’m just going to draw some conclusions of my own after experiencing both GraphQL and REST from two roles, together and separate: provider and consumer.
The API design & choosing the right paradigm
Most of the cases when the discussion goes down to what API is someone using in a project the standard answer is REST, and this is normal since it is building trust for about two decades now and many big vendors build on it. The thing about REST APIs is that it is really hard to correctly understand it and easy to create a complete mess if you are unprepared.
Before confidently saying that you are using a clean REST API be sure you see its benefits and comprehend all the “behind the scenes” mechanics. Depending on the moment you find yourself in the application’s growth, get a full picture of the reality of implementations and approaches and see if you are not only building a “so-called-REST” API.
More often than not we are building APIs that although are copying some REST principles and get the REST API stamp, do not check all the required constraints. Be careful, just because you build an API that uses HTTP protocol faithfully it doesn’t mean it is REST.
An important step is actually getting the grasp of the protocol and the way it should be used on both consumers and producers. If you dare to try, a good metric of whether or not you are on the right path is how coupled is your client to the server. If you can’t easily make them evolve independently most probably you are only building an HTTP API.
When talking about creating the API design, the approach is a bit different from GraphQL to REST. With GraphQL you don’t need to have it all figured out from the beginning. Until you actually start building your queries and give value to their performance, you can delay the actual understanding of how your client will consume your API. REST, on the other hand, asks you to go through the process of understanding what your client is waiting for before starting the implementation. Everything revolves around your user’s needs if you are able to identify that, you can decide which way to take into creating the best version of your design, with the lowest cost as possible.
Every learning process comes with its cost, a good approach is to create a context where you can invest time in learning architecture styles the right way, especially if the final decision about the application approach is in your hands. The privilege of making decisions about your API style or architecture comes with the responsibility of gaining an overview of cases, tradeoffs and benefits, and the risks of applying certain constraints to the system you are building.
As we were discussing above, as vital as it is to research the way your users interact with your API so it is understanding that one product differs from another when it comes to reaching their specific purpose, so there is no magic solution that suits them all. As an architect, you have to build from experience and be able to distinguish which one to use and when. Last but not least, take good care of leaving room for building features that might appear along the way. From experience I can say, it is challenging to change an API after being used. Although not impossible, this process takes time, effort and generates a lot of frustration. It is worth getting the knowledge and overall picture of how some patterns, best practices or even the protocol that you want to use fit in your business and technical context. This way you prepare yourself for the future.
Regarding this big debate between GraphQL and REST API let’s put it this way, if you don’t have the time and resources to put effort into strengthening your knowledge on HTTP and all its implications, on how to make the most of hypermedia as the engine of application state, on how to manipulate resources only through their representations, etc, maybe it is better to use GraphQL than create some unstable “so-called-REST” API.
GraphQL & REST
There are a lot of voices out there taking parts about which one is better, of course, all perspectives are built on personal context and so they are subjective depending on what sort of experience one had, good or bad. I was always curious about this sort of debates but my interest has grown lately and did some extra research especially because I really don’t think that one is better than the other. If you start the conversation with this “fight” in mind maybe you are not getting the point of having different attitudes to choose from. I’ll add some of the metrics I considered most relevant while “comparing” the two, and let you give the verdict.
- Is all about the client-server relationship — focus on the decoupling of client from the server
- Works with any representation: JSON or XML, most of the times
- Helps your API scale if clients respect the rules
- Uniformity: if you’re using HTTP don’t try to reinvent the wheel, just use HTTP features whenever possible
- Allows the system to scale and its components can evolve independently(goes well with the microservices architecture)
- Proven for decades
- Server-driven application state (server tells you what you can call)
- Design first, you have to think about use cases upfront & design resources
- Multiple APIs for specific client needs
On what you should pay attention
- Hard to pull off: steep learning curve
- Requires clients to play along
- Poor or no tooling for clients
- No framework or tooling guidance
- Requires discipline on all sides
- It is easy to create a big mess in your app if you use it wrong
To be fair, REST is the data-fetching equivalent of going to a restaurant and being asked “What do you want? We’ll give you what we have.” — Ryan Glover
- Easy to design and to consume
- Effortless consistency between the APIs
- For a specific request, you get a specific response
- Mutations for creates, updates, deletes, etc.
- Reduces the number of HTTP requests necessary to retrieve data for multiple resources, known as the “HTTP N+1 Problem”
- Built-in introspection
- Easy to keep consistent and to govern
- Design later gives you the possibility to evaluate in time what queries will users do and then optimize them
- One API for all client needs — resources declaring their own
On what you should pay attention
- Neglects the problems of the distributed system
- Application state is not driven by the server that might bring some coupling
- Query optimization — put some effort into understanding the strategy behind
- Bikeshedding (content negotiation, network errors, caching, etc).
- You have full control on scaling and performance — that might create some difficulties
- JSON representation only
- The approach was not embraced by as many vendors to have some more relevant feedback
GraphQL’s biggest problem may be that although it’s better, it’s not “better enough”. The bar set by REST is low, but it’s high enough to work and is adequate for most purposes. — Brandur Leach
Choices are everywhere in the life of a system, whether we talk about best practices, guidelines, API design or strategy. Above all, it is vital to understand what are the consequences of our choices, when we are saying yes to REST, so-called-REST or GraphQL we are at the same time saying no to the others. While we are considering the characteristics of one approach we are also accepting the price they come with in the long run.
If you are starting from scratch my suggestion is to take a good look at the product or system that you want to build, take into consideration all visible risks, build from experience — whether it is your experience or you ask for consultancy, weigh the impact of your decisions and take responsibility for all. Forget about finding the BEST API approach, and quit creating battles where they don’t exist, go with the choice that satisfies the requirements and resources that you have, pick what you NEED depending on your use cases and API goals.
Chase characteristics like scalability, performance, maintainability, and adaptability. Instead of staying safe in the corner with your long-trusted technologies, be curious, experiment and always question what you know, since technologies are evolving so rapidly.
Keep on learning, building and be excellent!