Disclaimer: I will not try to sell you whether or not you should build an API or not in your projects. This is an article based on my personal experience with GraphQL, JSON APIs and not API at all.
I've been building this things for over 7 years, during that time I've been using many different tools to create, document and test them. Usually when building an application that needs an API, I would start by thinking about the resources we will need,
roles etc. Then I would think about the way we can store the information about them, a MySQL database? maybe a NoSQL? who knows?.
One thing has been consistent across all of the options and flavors I've tried and that is the need to build a consistent, performant and useful API for the clients that will use it and for that I always consult the mobile and front end developers who at the end of the day are the ones that will interact with it.
During the time I've been doing this, we ran into several issues with REST, issues that can be solved pretty quickly, let's talk about the most common ones one by one.
Many times the users will need to get a list of resources that have a relation to another resource, the typical example is Posts and Authors. The post is written by an author. so every time you get a post you will need to get the author for that post. The naive way of doing this is looping through the resources and calling the authors endpoint to get the author and display it. So if you have a page with 10 posts, you will be making 11 API calls in total just for that, which is not ideal and is worse when you have pages of 50. The way we typically solve this is by using includes, meaning in your API call for the posts list you append a query string parameter to the endpoint asking to include the authors. It will look something like this:
The API server can lazy load this relations and deliver all of the information needed in a single API call, our server is powerful enough to handle that and should not be any issue anymore.
One other thing we usually come across is the ability to show or not show certain information depending on who is the user or entity requesting it, this is usually solved by using an Authorization system that is able to identify who is requesting the information and what is able to see, most of the times this is solved by using a combination of OAuth 2 and a permissions system tied to a role or permissions list attached to the user that we can check against.
This is something that always comes up mostly when working with mobile applications that may have limited network connectivity, if we have a screen that requires information from multiple resources, we may be asked by the mobile or front end team to create specific endpoints to get all the data needed for the screen in a single network call, in this cases we may accept to create such endpoint or we can work together in a possible solution like caching or something like that.
There are many ways to document an API, some people use Swagger or OpenAPI, others prefer using static site generators, others use API documentation tools like Readme.io or framework specific tools. I don't think there is a lot of tooling issues here other than developer laziness to properly document the endpoints and what they need.
GraphQL has gained a lot of popularity over the last few years, I think is a great tool and specification and that it has a lot potential and use cases, the question is, Do you need GraphQL in your project?
I started working with GraphQL because a friend of mine (and my boss at the time) presented me this idea of a query language over HTTP that would allow us to build better APIs for our clients. At first I though it was unnecessary and I could not really see the benefits I would get from it instead of using a normal JSON or REST API. However we decided to give it a try and after a little bit more than 2 years of working with it I feel more confident to talk about when you should and should not use it.
The first thing you need to know about me is that I have never faced the issues GraphQL is designed to solve, so to me was really hard to reset my mindset of converting resources into queries and mutations and I was very exceptical about the idea in general.
In GraphQL you don't use HTTP status codes, because those are tied to HTTP and one of the goals of GraphQL is to be protocol agnostic in that sense. So seeing errors in the API with a 200 OK status code was shocking.
First of all, REST and GraphQL are 2 different things, they are not to be compared because you would be comparing apples and oranges, however, many people compare them because they have a use case in common. Serve and receive information between systems.
GraphQL is a query language, basically you define your data model using GraphQL SDL and then you allow your clients query or mutate the information in your backend using a typed system. If you think about it that way its great, because you can let your clients decide what they fetch and it will give you a lot of flexibility for the frontend. This also allows for smaller response bodies and depending on the engine you use to execute these queries your backend become more or less complex.
Of course I can't define every single aspect of GraphQL here but having this general idea will give us a few tools for the main topic.
At first I did not really see any difference, it was more like a different way of doing things, our first GraphQL API was pretty much a port of the traditional CRUD operations defined on queries and mutations, so we first tried to make a 1:1 model of what we were used to do in a REST API, we ended up with something like this
// GET api/users => users: [User]
Our GET users resource became a users query, returning an array of user objects
// POST api/users => createUser(input: CreateUserInput!): User
Our POST users resource to create a user became a createUser mutation that receives the payload and returns a user object
// PUT api/users/:id => updateUser(id: ID!, input: UpdateUserInput!): User
Our PUT users resource to update a user became the updateUser mutation receiving a user ID and a payload, returning a User Object.
And so on...
This felt weird to be honest, however we did get a few things out of the box like the documentation and a stronger typed system to define our schemas and data model, although we could have achieved something similar with OpenAPI and JSON Schema.
As the timed passed we learned more and realized this was not really the way we should have done it, so our second API was more use case oriented, we started creating queries and mutations based on the actual need of the app instead of plain objects that mimic the database structure, we started creating queries like
upgradeUserPlan and it felt a little better, we where creating the access to the information the frontend needed without worries that our API would be less REST like.
So this project went good and everyone was happy and we though that we were conquering the GraphQL world. Then the next question came to my mind. What if another app needs this API and we don't have the use cases developed in the schema for it? isn't the purpose of GraphQL allowing the client to fetch what they need?.
Don't get me wrong, the API works and it does what it is suppose to, it just feels weird again.
This led me to believe that "one API fits all" approach is really hard to accomplish with both GraphQL and traditional JSON or REST APIs.
I must say however that given the nature of native mobile apps and the limited connectivity they sometimes have, being able to deliver information in smaller response bodies and letting the client choose what to show including relationships in less network round trips was a huge gain for us. We really saw some of the potential GraphQL has in those situations.
My answer to this questions in tech are always, "It depends". And the reason for that is that every use case is different, every problem may have different solutions and there are MANY factors to consider before choosing what to use.
So in order to alleviate a little bit this issue, I've come up with the following reasons to consider when starting a project and deciding what to use.
The first questions I ask myself are:
Many times your clients will come to you saying they need an app, and after they expose their idea you realize they want to build a blog with a few sections that require some interactivity and maybe it needs to be responsive, but it does not need to be downloaded from an app store and probably needs really good SEO. In this situation I tend to run away from making an API with a React or Vue SPA, is just overkill, KISS! (Keep it simple Stunning young man/woman XD).
Let's say your client wants to build a web app with user registration, probably some Stripe integration for subscriptions and features that the client can access based on the tier of their plan, BUT, without other clients accessing this like a iOS app or a KIOSK Android app. In this situation I would think on a simple Laravel app with blade and a few Vue JS components for interactivity. I would not think of it as an SPA that needs an API. Still KISS! (Keep it simple Stunning young man/woman XD).
So here, you are thinking about a backend that will serve the information for your App, app that will be deployed to a store and that won't persist information locally and needs to store it "In the cloud". Here is where I start asking a subset of questions about the use case to get a closer to our best solution for our use case.
To help here, I always refer to an old friend (we are not really friends, he is too famous and important to know about me XD), Phil Sturgeon who created a very effective and helping decision tree to choose the right API Paradigm. I encourage you to go read his article and come back.
Now that you are back, you may have a better idea how the answer to those questions may help you identify if you need a JSON or REST API, or if you need to create GraphQL server.
I've used both, GraphQL and REST and I can say that you can really make a mess with both, but also you can make GREAT things with both, so be wise picking your paradigm and don't forget that with a great power, comes a great responsibility, and you should ALWAYS look for your client's, the systems or people that will use your API (or not) providing them the tools and information to set them up for success. No matter the paradigm you use, if you have a great developer experience your APIs will be loved.
Well I've never worked with GRPC so I can't talk about it. BAAS systems like Amplify (AWS AppSync) or Firebase are also great options if you are looking for vendor locking and auto scale and you are not worried about the costs, look for this options, they may be a good fit. What I do want to make sure you do is not create an API if you don't really need it. Working in a blog in react with a headless CMS when you just want to publish some articles is overkill.