Authors: Olaf Zimmermann, Uwe Zdun (@uwe_zdun), Mirko Stocker (@m_st), Cesare Pautasso (@pautasso), Daniel Lübke (@dluebke)
Associate Editor: Niko Mäkitalo (@nikkis)
The Microservice API Patterns at www.microservice-api-patterns.org distill proven solutions to recurring service interface design and specification problems such as finding well-fitting service granularities, promoting independence among services, or managing the evolution of a microservice API.
It is hard to escape the term microservices these days. Much has been said about this rather advanced approach to system decomposition since James Lewis’ and Martin Fowler’s Microservices Blog Post from April 2014. For instance, IEEE Software devoted a magazine article, a two-part Insights interview (part 1, part 2) and even an entire special theme issue to the topic.
Early adopters’ experiences suggest that service design requires particular attention if microservices are supposed to deliver on their promises:
- How many service interfaces should be exposed?
- Which service cuts let services and their clients deliver user value jointly, but couple them loosely?
- How often do services and their clients interact to exchange data? How much and which data should be exchanged?
- What are suitable message representation structures, and how do they change throughout service lifecycles?
- How to agree on the meaning of message representations – and stick to these contracts in the long run?
The Microservice API Patterns (MAP) at www.microservice-api-patterns.org cover and organize this design space providing valuable guidance distilled from the experience of API design experts.
What makes service design hard (and interesting)?
An initial microservice API design and implementation for systems with a few API clients often seem easy at first glance. But a lot of interesting problems surface as systems grow larger, evolve, and get new or more clients:
- Requirements diversity: The wants and needs of API clients differ from one another, and keep on changing. Providers have to decide whether they offer good-enough compromises or try to satisfy all clients’ requirements individually.
- Design mismatches: What backend systems can do and how they are structured, might be different from what clients expect. These differences have to be dealt with during the API design.
- Freedom to innovate: The desire to innovate and market dynamics such as competing API providers trying to catch up on each other lead to the need to change and evolve the API. However, publishing an API means giving up some control and thus limiting the freedom to change it.
- Risk of change: Introducing changes may result in possibly incompatible evolution strategies going beyond what clients expect and are willing to accept.
- Information hiding: Any data exposed in an API can be used by the clients, sometimes in unexpected ways. Poorly designed APIs leak service implementation secrets and let the provider lose its information advantage.
Such conflicting requirements and stakeholder concerns must be balanced at the API design level; here, many design trade-offs can be observed. For instance, data can be transferred in a few calls that carry lots of data back and forth, or alternatively, many chatty, fine-grained interactions can be used. Which choice is better in terms of performance, scalability, bandwidth consumption and evolvability? Should the API design focus on stable and standardized interfaces or rather focus on fast-changing and more specialized interfaces? Should state changes be reported via API calls or event streaming? Should commands and queries be separated?
All of these – and many related – design issues are hard to get right. It is also hard to oversee all relevant consequences of a design decision, for instance regarding trade-offs and interdependencies of different decisions.
Enter Microservice API Patterns (MAP)
Our Microservice API Patterns (MAP) focus – in contrast to existing design heuristics and patterns related to microservices – solely on microservice API design and evolution. The patterns have been mined from numerous public Web APIs as well as many application development and software integration projects the authors and their industry partners have been involved in.
MAP addresses the following questions, which also define several pattern categories:
- The structure of messages and the message elements that play critical roles in the design of APIs. What is an adequate number of representation elements for request and response messages? How are these elements structured? How can they be grouped and annotated with supplemental usage information (metadata)?
- The impact of message content on the quality of the API. How can an API provider achieve a certain level of quality of the offered API, while at the same time using its available resources in a cost-effective way? How can the quality tradeoffs be communicated and accounted for?
- The responsibilities of API operations. Which is the architectural role played by each API endpoint and its operations? How do these roles and the resulting responsibilities impact microservice size and granularity?
- API descriptions as a means for API governance and evolution over time. How to deal with lifecycle management concerns such as support periods and versioning? How to promote backward compatibility and communicate breaking changes?
So far, we have presented ten patterns at EuroPLoP 2017 and EuroPLoP 2018; about 35 more candidate patterns are currently being worked on. The published patterns and supporting material are available on the MAP website that went live recently. The papers are available via this page.
Sample Patterns for Communicating and Improving Interface Quality
To illustrate MAP a bit further, we summarize five patterns on communicating and improving API qualities below. We also outline their main relationships.
|Figure: Relationships between Selected Patterns for Communicating and Improving Interface Quality.
- API Key: An API provider needs to identify the communication participant it receives a message from to decide if that message actually originates from a registered, valid customer or some unknown client. A unique, provider-allocated API Keyper client to be included in each request allows the provider to identify and authenticate its clients. This pattern is mainly concerned with the quality attribute security.
- Wish List: Performance requirements and bandwidth limitations might dictate a parsimonious conversation between the provider and the client. Providers may offer rather rich data sets in their response messages, but not all clients might need all of this information all the time. A Wish List allows the client to request only the attributes in a response data set that it is interested in. This pattern addresses qualities such as accuracy of the information needed by the consumer, response time, and performance, i.e., the processing power required to answer a request.
- Rate Limit: Having identified its clients, an authenticated client could use excessively many resources, thus negatively impacting the service for other clients. To limit such abuse, a Rate Limit can be employed to restrain certain clients. The client can stick to its Rate Limit by avoiding unnecessary calls to the API. This pattern is concerned with the quality attributes of reliability, performance, and economic viability.
- Rate Plan: If the service is paid for or follows a freemium model, the provider needs to come up with one or more pricing schemes. The most common variations are a simple flat-rate subscription or a more elaborate consumption-based pricing scheme, explored in the Rate Plan pattern. This pattern mainly addresses the commercialization aspect of an API.
- Service Level Agreement: API providers want to deliver high-quality services while at the same time using their available resources economically. The resulting compromise is expressed in a provider’s Service Level Agreement(SLA) by the targeted service level objectives and associated penalties (including reporting procedures). This pattern is concerned with the communication of any quality attribute between API providers and clients. Availability is an example of a quality that is often expressed in such an SLA.
More patterns and pattern relationships can be explored at www.microservice-api-patterns.org. In addition to the patterns, you find there additional entry points such as a cheat sheet and various pattern filters such as patterns by force, and patterns by scope (phase/role).
Microservice API Patterns (MAP) is a volunteer project focused on the design and evolution of Microservice APIs. We hope you find the intermediate results of our ongoing efforts useful. They are available at www.microservice-api-patterns.org – we will be glad to hear about your feedback and constructive criticism. We also welcome contributions such as pointers to known uses or war stories in which you have seen some of the patterns in action.
The patterns in MAP aim at sharing timeless knowledge on distributed system APIs. While trends like microservices come and go, the fundamental design problems of exposing remote APIs will not go out of fashion any time soon!