Skip to main content

API Versioning

Context

Microservices are being adopted. The internals of the microservices are hidden behind its API. There is a need to make changes to a microservice API that are not backward compatible. THe project is in a phase where breaking all consuming microservices is not an option.

Problem

  • Breaking API changes influence consuming microservices.
    • The system becomes unstable and/or release coordination is required to introduce breaking API changes.

Solution

Introduce a new version of the API while maintaining the old version in parallel. Once all consumers migrated, remove the old API.

Technically, this can be implemented by either deploying two different versions of the same microservice, one with the old version of the API and one with the new version of the API. L16 suggests to rather not do this, but implement the old and the new API version within the microservice instead. The old API can redirect the received calls to the new API, potentially making the support of multiple versions possible.

Offering two API versions in parallel for the migration of consuming microservices is complex and costly. Interviewee B recommends to not go beyound supporting 2 or 3 API versions at once, but rather complete the migration of consumers before.

The process of API versioning should be standardized across all microservices. This includes the technical details, e.g. how different API versions are indicated in an API endpoint, but also the processes around it.

L32 proposes strategies on how to communicate new API versions:
  • Establish a grace period in which consuming microservices shall migrate. If they don't they have to bear the consequences. - Monitor the API usage to evaluate if old version still receiving traffic. - Incentivize the migration by showing alerts on usage of the old API versions, or even disabling the API for a short time.

Maturity

Proposed, evaluation required.

Sources of Evidence

L3:

  • Solution to breaking service contracts: Versioning
  • can make deployment even more complex
    • => people don't recommend versioning
  • Alternative: tolerant reader pattern

L7:

  • Context: raises practitioner questions
  • service versioning and evolution among them
    • change of interface in terms of syntax and/or semantics
  • backward compatibility has to be addressed;
    • no versions at all
    • indepotency of services => definition needed

L12:

  • Service versioning as solution to breaking contract changes
    • makes deployment of each service more complex
    • thus, people do not recommend service versioning
  • alternative: tolerant reader, consumer-driven contracts

L16:

  • coexistence of different versions over long period of time
    • Option 1: a service of version 1 and a service of version 2
      • highly discouraged => both code bases need to be maintained in parallel
    • Option 2: one service of new version accessible with old and new interface
      • only needs to internally rederict to new interface
      • When version is not required anymore => remove redirection parts
      • possible to chain multiple versions like this
      • impl changes can be maintained in single code base

L19:

  • microservice explosion, different versions make it worse
  • need for service discovery, routing mechanisms, configuration management

L20:

  • API versioning in 3rd place in pains at design stage
  • API becomes contract between microservices
    • contracts should not be violated if goal to continue communication with other microservices
    • => impacts versioning of APIs => pain the design of MSA
    • => new API versions need to be retro-compatible to violate contracts
  • need for methodologies and techniques to ease the versioning of microservices

L20:

  • Nicolai: Many people recommend microservices without pointing to problems
    • among them: versioning and error handling in distributed systems

L32:

  • Expand the contract
    • even if all services follow robustness principle => cannot sometimes avoid breaking compatability
    • rather than modifying interface to break compatibility: add new interface
    • Led consumers migrate to new interface
    • Finally, remove old interface
    • => make changes but keep compatability
  • How to ensure consumer migrate
    • Grace period
      • mark as deprecated
      • turn off after grace monitoring => consequences in responsibility of consuming team
    • Interface usage monitoring
      • to evaluate if old version still receiving traffic
      • safe migration if no traffic
    • Incentivize migration
      • after grace period runs out, apply tactic
      • show alerts on usage
      • temprarily disable interface => consumers will ask what happened => give another time limit to migrate

L34:

  • Table 1: service versioning should be part of architecture, more open to change
    • SOA: maintain multiple same services of different versions
      • one of main issues of SOA: cases where over 20 different versions of service were maintained to accept different data
      • => demanding monitoring and maintenance

L53:

  • Context: name resolution policy between service API and endpoint
  • API gateway can bind to new version of the microservice
    • replacement is easy if API is backward compatible in syntax and semantic
    • if compatible: create new virtual object and methods, bind to microservice of the new version, run both versions in parallel until all clients shift to new version

L58:

  • Context: live schema migration
  • rules to change DB schema
      1. update of schema must be done in isolation to not propagete change to subscribers
      • Example: before removing attribute: add virtual attribute of same name
      1. semantics of attribute must not change
      • Example: type must not change
      • Instead of changing, add new attribute and eventually stop publishing the old one
      1. Publishing new attribute often motivated by subscriber
      • When changing both sides, deploy the publisher first then the subscriber
  • production nodes: deploy heavily refactored service with own db separately instead
    • both versions in parallel for some time => do QA on new service
    • possibility to roll back easily
    • => avoid downtimes

L59:

  • Microservice provide old while, even while providing new API with new features
    • good indicator for service size: so small and simple so that the API can remain stable
  • structure of API calls should stay stable and backward compatible

LN42:

  • Context: disadvantages of microservices
  • versioning among others

Interview A:

  • Challenge: Versioning with 50+ nucriservices
    • Which is compatible to what?
    • Which one is part of our current product?
    • big topics
  • Semantic versioing, works quite well for their project

Interview B:

  • Important topic: API versioning and who drives the interface
  • often see classic conformist pattern: one gives the direction
    • Example: Facebook, Twitter and Co. and all have to change
    • rather untypical in normal projects
  • => consumer-supplier pattern
    • prividing service does not mean we can't with each other
    • together think about how interface should look like to fit both sides and be fit for the future
    • => versioning
  • Someone said you don't need versioning strategy
    • in the sense how to number and when it is downwards compatible
    • but you need a change strategy!
      • how to generally handle change in the system
      • evolution sometimes means combining services => more than just interface versioning
  • If only one or two services => there is only the most recent version
    • gets worse with many services and the business flows over multiple services
      • can become deliberately complex => test potentially all permutations
      • can't handle that
    • advise: don't support more than max. 2 or 3 versions at once
      • just to get switch for zero downtime
      • but do yourself a favor to not support 50 version
  • How does versioning fit event-driven messagign?
    • refers to event payload
    • sometimes also header
    • keep payload backward compratible or versioning => consuming party can still process it
  • GraphQL as interface between microservices
    • becomes interesting when using different versions in the dependency graph spanned by GraphQL
    • same can be done using HATEOAS => use links to easily switch to new version

Interview D:

  • Do I version or no?
  • What do I do instead if I don't version? => how to keep the backward compatability?
  • If versioning: how?
    • mechanism to announce the removal of a service
    • authentication and authorization => how to forward credentials, tokens, etc.
    • => define minimal standards to not start always at zero and reduce coordination to a required minimum

Interview E:

  • If deployment of a vertical (backend and frontend together) together => no need to version within the vertical

Interview F:

  • Context: coordinated releases?
  • At the beginning: everything flowing => strict versioning would be a hurdle
    • need to make mistakes and deal with consequences
    • needs to be possible at the start of a project