Content
A progressive fragmentation of client devices and the evolution of API driven by new product features is the driver for a proper API lifecycle management. Consumers may not adopt to API changes that quickly and stick on a particular API as long as possible or manage an upgrade as part of their own application lifecycle.
Client applications of OpenWMS.org API are not fragmented in that degree we see the fragmentation with mobile devices but also in projects of the logistics domain we deal with arbitrary devices across varying customers. In addition to that software in production is updated rarely.
One approach to deal with these challenges is to always be backward compatible and never break existing API consumer code. Stripe.com does an excellent job in API cultivation & care and explains how this could work in a fantastic blog article. Nevertheless managing and taking care of many clients is complex and may blow up the API.
Another much more simpler and often used approach is to version the API in that the URI to an API resource contains (or is tagged with) a version identifier (e.g. v1). Precisely two URI that contain a different version identifier are not the same and do not point to the same resource.
Responsibility
If we decide to version our API resources and introduce a version identifier as part of the URI, we also need to question who takes responsibility of managing the API lifecycle for each microservice. Does the development team decide when breaking changes are introduced and a new version of an API is raised? Or does an overall product management coordinate and manage major API changes and defined the public product API?
Like often the answer is: It depends. For OpenWMS.org microservice API, the development team is responsible for the API lifecycle whereas a manager role focuses, manages and communicates the public API to particular parties. Several public exposed API may exist in an omni-channel architecture where each API is a composition or a new formation of existing microservice API. In this case, a management role is in charge to communicate upcoming changes and consider client requirements and feedback.
Lifecycle
In general, the team that maintains a microservice is responsible for the API management of that service. But some overall principles exist that should be followed across all microservice API.
Maintain at least two active API versions. The newer version is the preferred version to use and the target for migration. The older version may be flagged as deprecated
Always strive for API evolution and avoid breaking changes. This is a trade-off and must be in balance with cost, efficiency and simplicity
A version identifier can be introduced in at least two different ways. Popular approaches have the version identifier as part of the query path or as separate HTTP header argument (constraint: REST over http).
Version in Query Path or Authority
The version identifier is either part of the HTTP query path or the authority.
Examples:
Query Path: https://api.foo.bar/v1/cards
Authority: https://v1.api.foo.bar/cards
For microservice API we prefer to use the version identifier as part of the query path
The version identifier starts with a 'v' character followed by an integer starting with 1
This is more convenient for a system of microservices that does not depend on hostnames nor authorities. The identifier as part of the query path determines the corresponding resource no matter where the service is hosted on.
OpenWMS.org microservices have the API version identifier as part of the HTTP query path, as a prefix to the primary resource identifier
For public API, or those with a product character (AaaP - API as a Product), the version may be introduced as part of the authority. In particular for API that are built as product and for the purpose of different channels this is often used. The diagram below shows one part of the current OpenWMS.org API.
Version encoded in Accept Header
In contrast to use a fixed version identifier as part of the URI it is also possible to encode the version or respectively the representation type within the HTTP Accept Header. A client requests the server for a specific resource in a particular representation format. That means the same URI could be requested with different representation formats to get different representations of the same resource.
In this example a Client asks for a representation of a TransportUnit of type application/vnd.openwms.transport-unit-v1+json
. The server knows this format and sends back a JSON representation of that particular version.
A valid custom representation format has the following naming pattern:
application/vnd.<product>.<resource>-<version identifier>+(json|xml)
application | Standardized prefix |
vnd | Abbreviation that signals the vendor tree |
<product> | Custom product identifier |
<version-identifier> | Prefix āvā with increasing integer value |
(json|xml) | Either JSON or XML response format requested |
all other symbols are fixed characters.
The approach to encode the requested version into the Accept header is rather the exceptional case and is only used in API that match the same query path but different representation formats are supported.