Granularity is an essential principle of REST API design. As we understand, business functions divided into many small actions are fine-grained, and business functions divided into large operations are coarse-grained.
However, discussions about what level of granularity that needs to be in APIs may vary, we will get distinct suggestions, and even end up in debates. Regardless, its best to decide based upon business functions and its use cases, as granularity decisions would undoubtedly vary on a case by case basis.
This article discusses a few points on how API designers would need to choose their RESTful service granularity levels.
Coarse-Grained and Fine-Grained APIs
In some cases, calls across the network may be expensive, so to minimize them, coarse-grained APIs may be the best fit, as each request from the client forces lot of work at the server side, and in fine-grained, many calls are required to do the same amount of work at the client side.
Example: Consider a service returns customer orders in a single call. In case of fine-grained, it returns only the customer IDs, and for each customer id, the client needs to make an additional request to get details, so n+1 calls need to be made by the clients. It may be expensive round trips regarding its performance and response times over the network.
In a few other cases, APIs should be designed at the lowest practical level of granularity, because combining them is possible and allowed in ways that they suit the customer needs.
Example: An electronic form submission may need to collect addresses as well as, say, tax information. In this case, there are two functions: one is a collection of applicant’s whereabouts, and another is a collection of tax details. Each task needs to be addressed with a distinct API and requires a separate service because an address change is logically a different event and not related to tax time reporting, i.e., why one needs to submit the tax information (again) for an address change.
Levels of Granularity
Level of granularity should satisfy the specific needs of business functions or use cases. While the goal is to minimize calls across the network and for better performance, we must understand the set of operations that API consumers require and how they would give a better idea of the “correctly-grained” APIs in our designs.
At times, it may be appropriate that the API design supports both coarse-grained as well as fine-grained to give the flexibility for the API developers to choose the right APIs for their use cases.
The following points may serve as some basic guidelines for the readers to decide their APIs granularity levels in their API modeling.
- In general, consider that the services may be coarse-grained, and APIs are fine-grained.
- Maintain a balance between the amount of response data and the number of resources required to provide that data. It will help decide the granularity.
- The types of performed operations on the data should also be considered as part of the design when defining the granularity.
- Read requests are normally coarse-grained. Returning all information as required to render the page; it won’t hurt as much as two separate API calls in some cases.
- On the other hand, write requests must be fine-grained. Find out everyday operations clients needs, and provide a specific API for that use case.
- At times, you should use medium grained, i.e., neither fine-grained or coarse-grained. An example could be as seen in the following sample where the nested resources are within two levels deep.
While the above guideline may understandably lead to more API deployment units, this can cause annoyances down the line. There are patterns, especially the API Gateway, that bring a better orchestration with those numerous APIs. Orchestrating the APIs with optimized endpoints, request collapsing, and much more helps in addressing the granularity challenges.