Microservice API Patterns

Olaf Zimmermann, Mirko Stocker, Uwe Zdun,
Daniel Lübke, Cesare Pautasso

The Book: Patterns for API Design

Simplifying Integration with Loosely Coupled Message Exchanges (Addison-Wesley)

Foundation

Frontend Integration

How can client-side end-user interfaces that are physically separated from server-side business logic and data storage be populated and updated with computing results, result sets from searches in data sources, and detailed information about data entities? How can application frontends invoke activities in a backend or upload data to it?

Let the backend of a distributed application expose its services to one or more application frontends via a message-based remote Frontend Integration API.

Backend Integration

How can distributed applications and their parts, which have been built independently and are deployed separately, exchange data and trigger mutual activity while preserving system-internal conceptual integrity without introducing undesired coupling?

Integrate the backend of a distributed application with one or more other backends (of the same or other distributed applications) by exposing its services via a message-based remote Backend Integration API.

Public API

How can an API be made available to an unlimited and/or unknown number of API clients outside the organization that are globally, nationally, and/or regionally distributed?

Expose the API on the public Internet along with a detailed API Description that describes both functional and nonfunctional properties of the API.

Community API

How can the visibility of and the access to an API be restricted to a closed user group that does not work for a single organizational unit but for multiple legal entities (such as companies, nonprofit/nongovernment organizations, and governments)?

Deploy the API and its implementation resources securely in an access-restricted location so that only the desired user group has access to it—for instance, in an extranet. Share the API Description only with the restricted target audience.

Solution-Internal API

How can access to and usage of an API be limited to an application, for instance, components in the same or another logical layer and/or physical tier?

Decompose the application logically into components. Let these components expose local or remote APIs. Offer these APIs only to system-internal communication partners such as other services in the application backend.

API Description

Which knowledge should be shared between an API provider and its clients? How should this knowledge be documented?

Create an API Description that defines request and response message structures, error reporting, and other relevant parts of the technical knowledge to be shared between provider and client. In addition to static and structural information, also cover dynamic or behavioral aspects, including invocation sequences, pre- and postconditions, and invariants. Complement the syntactical interface description with quality management policies as well as semantic specifications and organizational information.

Endpoint Roles

Processing Resource

How can an API provider allow its clients to trigger an action in it?

Add a Processing Resource endpoint to the API exposing operations that bundle and wrap application-level activities or commands.

Information Holder Resource

How can domain data be exposed in an API, but its implementation still be hidden? How can an API expose data entities so that API clients can access and/or modify these entities concurrently without compromising data integrity and quality?

Add an Information Holder Resource endpoint to the API, representing a data-oriented entity. Expose create, read, update, delete, and search operations in this endpoint to access and manipulate this entity. In the API implementation, coordinate calls to these operations to protect the data entity.

Operation Responsibilities

State Creation Operation

How can an API provider allow its clients to report that something has happened that the provider needs to know about, for instance, to trigger instant or later processing?

Add a State Creation Operation `sco: in -> (out,S')` that has a write-only nature to the API endpoint, which may be a Processing Resource or an Information Holder Resource.

Retrieval Operation

How can information available from a remote party (the API provider, that is) be retrieved to satisfy an information need of an end user or to allow further client-side processing?

Add a read-only operation `ro: (in,S) -> out` to an API endpoint, which often is an Information Holder Resource, to request a result report that contains a machine-readable representation of the requested information. Add search, filter, and formatting capabilities to the operation signature.

State Transition Operation

How can a client initiate a processing action that causes the provider-side application state to change? How can API clients and API providers share the responsibilities required to execute and control business processes and their activities?

Introduce an operation in an API endpoint that combines client input and current state to trigger a provider-side state change `sto: (in,S) -> (out,S')`. Model the valid state transitions within the endpoint, which may be a Processing Resource or an Information Holder Resource, and check the validity of incoming change requests and business activity requests at runtime.

Computation Function

How can a client invoke side-effect-free remote processing on the provider side to have a result calculated from its input?

Introduce an API operation `cf` with `cf: in -> out` to the API endpoint, which often is a Processing Resource. Let this Computation Function validate the received request message, perform the desired function cf, and return its result in the response.

Information Holder Types

Operational Data Holder

How can an API support clients that want to create, read, update, and/or delete instances of domain entities that represent operational data: data that is rather short-lived, changes often during daily business operations, and has many outgoing relations?

Tag an Information Holder Resource as Operational Data Holder and add API operations to it that allow API clients to create, read, update, and delete its data often and fast.

Master Data Holder

How can I design an API that provides access to master data that lives for a long time, does not change frequently, and will be referenced from many clients?

Mark an Information Holder Resource to be a dedicated Master Data Holder endpoint that bundles master data access and manipulation operations in such a way that the data consistency is preserved and references are managed adequately. Treat delete operations as special forms of updates.

Reference Data Holder

How should data that is referenced in many places, lives long, and is immutable for clients be treated in API endpoints? How can such reference data be used in requests to and responses from Processing Resources or Information Holder Resources?

Provide a special type of Information Holder Resource endpoint, a Reference Data Holder, as a single point of reference for the static, immutable data. Provide read operations, but no create, update, or delete operations in this endpoint.

Data Transfer Resource

How can two or more communication participants exchange data without knowing each other, without being available at the same time, and even if the data has already been sent before its recipients became known?

Introduce a Data Transfer Resource as a shared storage endpoint accessible from two or more API clients. Provide this specialized Information Holder Resource with a globally unique network address so that two or more clients can use it as a shared data exchange space. Add at least one State Creation Operation and one Retrieval Operation to it so that data can be placed in the shared space and also fetched from it.

Representation Elements

Atomic Parameter

How can simple, unstructured data (such as a number, a string, a Boolean value, or a block of binary data) be exchanged between API client and API provider?

Define a single parameter or body element. Pick a basic type from the type system of the chosen message exchange format for it. If justified by receiver-side usage, identify this Atomic Parameter with a name. Document name (if present), type, cardinality, and optionality in the API Description.

Atomic Parameter List

How can multiple related Atomic Parameters be combined in a representation element so that each of them stays simple, but their relatedness becomes explicit in the API Description and the runtime message exchanges?

Group two or more simple, unstructured data elements in a single cohesive representation element to define an Atomic Parameter List that contains multiple Atomic Parameters. Identify its items by position (index) or by a string-valued key. Identify the Atomic Parameter List as a whole with its own name as well if that is needed to process it in the receiver. Specify how many elements are required and permitted to appear.

Parameter Tree

How can containment relationships be expressed when defining complex representation elements and exchanging such related elements at runtime?

Define a Parameter Tree as a hierarchical structure with a dedicated root node that has one or more child nodes. Each child node may be a single Atomic Parameter, an Atomic Parameter List, or another Parameter Tree, identified locally by a name and/or by position. Each node might have an exactly-one cardinality, but also a zero-or-one cardinality, an at-least-one cardinality, or a zero-or-more cardinality.

Parameter Forest

How can multiple Parameter Trees be exposed as request or response payload of an API operation?

Define a Parameter Forest comprising two or more Parameter Trees. Locate the forest members by position or name.

Element Stereotypes

Data Element

How can domain/application-level information be exchanged between API clients and API providers without exposing provider-internal data definitions in the API? How can API client and API provider be decoupled from a data management point of view?

Define a dedicated vocabulary of Data Elements for request and response messages that wraps and/or maps the relevant parts of the data in the business logic of an API implementation.

Metadata Element

How can messages be enriched with additional information so that receivers can interpret the message content correctly, without having to hardcode assumptions about the data semantics?

Introduce one or more Metadata Elements to explain and enhance the other representation elements that appear in request and response messages. Populate the values of the Metadata Elements thoroughly and consistently; process them as to steer interoperable, efficient message consumption and processing.

Id Element

How can API elements be distinguished from each other at design time and at runtime? When applying domain-driven design, how can elements of the Published Language be identified?

Introduce a special type of Data Element, a unique Id Element, to identify API endpoints, operations, and message representation elements that have to be distinguished from each other. Use these Id Elements consistently throughout API Description and implementation. Decide whether an Id Element is globally unique or valid only within the context of a particular API.

Special Purpose Representations

API Key

How can an API provider identify and authenticate clients and their requests?

As an API provider, assign each client a unique token —- the API Key -— that the client can present to the API endpoint for identification purposes.

Error Report

How can an API provider inform its clients about communication and processing faults? How can this information be made independent of the underlying communication technologies and platforms (for example, protocol-level headers representing status codes)?

Reply with error codes in response messages that indicate and classify the faults in a simple, machine-readable way. In addition, add textual descriptions of the errors for the API client stakeholders, including developers and/or end users such as administrators.

Context Representation

How can API consumers and providers exchange context information without relying on any particular remoting protocols? How can identity information and quality properties in a request be made visible to related subsequent ones in conversations?

Combine and group all Metadata Elements that carry the desired information into a custom representation element in request and/or response messages. Do not transport this single Context Representation in protocol headers, but place it in the message payload. Separate global from local context in a conversation by structuring the Context Representation accordingly. Position and mark the consolidated Context Representation element so that it is easy to find and distinguish from other Data Elements.

Quality Management and Governance

Pricing Plan

How can the API provider meter API service consumption and charge for it?

Assign a Pricing Plan for the API usage to the API Description that is used to bill API customers, advertisers, or other stakeholders accordingly. Define and monitor metrics for measuring API usage, such as API usage statistics per operation.

Rate Limit

How can the API provider prevent API clients from excessive API usage?

Introduce and enforce a Rate Limit to safeguard against API clients that overuse the API.

Service Level Agreement

How can an API client learn about the specific quality-of-service characteristics of an API and its endpoint operations? How can these characteristics, and the consequences of not meeting them, be defined and communicated in a measurable way?

As an API product owner, establish a structured, quality-oriented Service Level Agreement that defines testable service-level objectives.

Data Transfer Parsimony

Pagination

How can an API provider deliver large sequences of structured data without overwhelming clients?

Divide large response data sets into manageable and easy-to-transmit chunks (also known as pages). Send one chunk of partial results per response message, and inform the client about the total and/or remaining number of chunks. Provide optional filtering capabilities to allow clients to request a particular selection of results. For extra convenience, include a reference to the next chunk/page from the current one.

Wish List

How can an API client inform the API provider at runtime about the data it is interested in?

As an API client, provide a Wish List in the request that enumerates all desired data elements of the requested resource. As an API provider, deliver only those data elements in the response message that are enumerated in the Wish List ("response shaping").

Wish Template

How can an API client inform the API provider about nested data that it is interested in? How can such preferences be expressed flexibly and dynamically?

Add one or more additional parameters to the request message that mirror the hierarchical structure of the parameters in the corresponding response message. Make these parameters optional or use Boolean as their types so that their values indicate whether or not a parameter should be included.

Conditional Request

How can unnecessary server-side processing and bandwidth usage be avoided when frequently invoking API operations that return rarely changing data?

Make requests conditional by adding Metadata Elements to their message representations (or protocol headers) and processing these requests only if the condition specified by the metadata is met.

Request Bundle

How can the number of requests and responses be reduced to increase communication efficiency?

Define a Request Bundle as a data container that assembles multiple independent requests in a single request message. Add metadata such as identifiers of individual requests and bundle element counter.

Reference Management

Embedded Entity

How can one avoid sending multiple messages when their receivers require insights about multiple related information elements?

For any data relationship that the client wants to follow, embed a Data Element in the request or response message that contains the data of the target end of the relationship. Place this Embedded Entity inside the representation of the source of the relationship.

Linked Information Holder

How can messages be kept small even when an API deals with multiple information elements that reference each other?

Add a Link Element to messages that pertain to multiple related information elements. Let this Link Element reference another API endpoint that represents the linked element.

Versioning

Version Identifier

How can an API provider indicate its current capabilities as well as the existence of possibly incompatible changes to clients in order to prevent malfunctioning of clients due to undiscovered interpretation errors?

Introduce an explicit version indicator. Include this *>Version Identifier* in the API Description and in the exchanged messages. To do the latter, add a Metadata Element to the endpoint address, the protocol header, or the message payload.

Semantic Versioning

How can stakeholders compare API versions to detect immediately whether they are compatible?

Introduce a hierarchical three-number versioning scheme x.y.z, which allows API providers to denote different levels of changes in a compound identifier. The three numbers are usually called major, minor, and patch versions.

Evolution Strategies

Two in Production

How can a provider gradually update an API without breaking existing clients but also without having to maintain a large number of API versions in production?

Deploy and support two versions of an API endpoint and its operations that provide variations of the same functionality but do not have to be compatible with each other. Update and decommission the versions in a rolling, overlapping fashion.

Aggressive Obsolescence

How can API providers reduce the effort for maintaining an entire API or its parts (such as endpoints, operations, or message representations) with guaranteed service quality levels?

Announce a decommissioning date to be set as early as possible for the entire API or its obsolete parts. Declare the obsolete API parts to be still available but no longer recommended to be used so that clients have just enough time to upgrade to a newer or alternative version before the API parts they depend on disappear. Remove the deprecated API parts and the support for it as soon as the deadline has passed.

Experimental Preview

How can providers make the introduction of a new API, or new API version, less risky for their clients and obtain early adopter feedback without having to freeze the API design prematurely?

Provide access to an API on a best-effort basis without making any commitments about the functionality offered, stability, and longevity. Clearly and explicitly articulate this lack of API maturity to manage client expectations.

Limited Lifetime Guarantee

How can a provider let clients know for how long they can rely on the published version of an API?

As an API provider, guarantee to not break the published API for a fixed timeframe. Label each API version with an expiration date.

Eternal Lifetime Guarantee

How can a provider support clients that are unable or unwilling to migrate to newer API versions at all?

As an API provider, guarantee to never break or discontinue access to a published API version.

Presentations

References (1/3)

References (2/3)

References (3/3)