What is the Right Service Granularity in APIs?
Expert architects and developers present the EMBEDDED ENTITY and LINKED INFORMATION HOLDER API design patterns to help you represent referenced data in an API.
Real-world APIs typically expose complex data and model parts such as Aggregates or Entities from a domain-driven design. Squeezing such complex, possibly nested data into a single JSON object in a HTTP request or response message is technically possible and often seen in practice, but might not always be an adequate choice. Many data elements contain references to others; for instance, think about orders and their order items or purchase orders referring to customers and products. An important question is how such references should be reflected in an API; answers to it determine the API endpoint and operation granularity, coupling characteristics, and other API qualities.
In this article, we present two API design patterns, EMBEDDED ENTITY and LINKED INFORMATION HOLDER, both eligible when deciding how to represent referenced data in an API. For more information and details on these two patterns (and 42 others), please refer to our book Patterns for API Design: Simplifying Integration with Loosely Coupled Message Exchanges (Addison Wesley Signature Series).
Introduction to API Quality
Modern software systems are distributed systems. Mobile and Web clients exchange information with backend API services, often hosted by a single or even multiple cloud providers, and different backends trigger activities in each other. Independent of the technologies and protocols used, messages travel through one or several API clients and their service providers in such systems. This places high demands on quality aspects of each API implementation: API clients expect any published API to be developer-friendly, reliable, responsive, and scalable. API providers must balance conflicting concerns to guarantee high service quality while ensuring cost-effectiveness.
API quality patterns can help resolve the following overarching design issue:
How to achieve a certain level of quality of an offered API while at the same time cost-effectively utilizing the available resources?
Arguably, it would be hard to find API designers and product owners who do not value intuitive understandability, splendid performance, and seamless evolvability. That said, any quality improvement comes at a price—a literal cost such as extra development effort, but also negative consequences such as an adverse impact on other qualities. This balancing act comes from the fact that some of the desired qualities conflict with each other. Just think about the almost classic performance versus security trade-offs.
In this article, we are specifically interested in the following questions:
Is it preferable to exchange several small messages or a few larger ones?
Is it acceptable that some clients might have to send multiple requests to obtain all the data required so that other clients do not have to receive data they do not use?
Option 1: Nested Data
One option is to embed the content of the referenced data record in the data element sent over the wire:
|Pattern: EMBEDDED ENTITY|
|Problem||How can one avoid sending multiple messages when their receivers require insights about multiple related information elements?|
|Solution||For any data relationship that the client wants to follow, embed a DATA ELEMENT in the message that contains the data of the target entity.|
This is a solution sketch for EMBEDDED ENTITY (note that all pattern names are set in SMALL CAPS):
We discuss the pros and cons of this inclusive design later in this article (and in our book).