Skip to main content

Backward Compatible APIs

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.

Problem

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

Solution

Keep APIs backward compatible as long as possible. For example, only add API fields but never remove them.

Such changes still require resilient consumers to not break them. The use of hypermedia concepts might help to restructure an API as well without influencing consumers.

Keeping an API backward compatible for a long time can add complexity to the internals of a service and lead to suboptimal API design. When becomes unfeasible or unbearable to keep an API backward compatible, consider versioning the API to allow a graceful migration towards the new API version.

In all cases, it makes sure to detect breaking backward compatibility, e.g., by using consumer-driven contract tests.

Maturity

Proposed, evaluation required.

Sources of Evidence

L7:

  • backward compatibility has to be addressed;
    • no versions at all
    • indepotency of services => definition needed

L20:

  • API becomes contract between microservices
  • new versions must be retro-compatible to avoid violating the contract => continue intercommunication

L32:

  • Robustness principle for code interacting with other services
    • be conservative in what you send, be liberal in what you accept from others
  • Example
    • service returns 2 fields
    • other 5 services use that service
    • => ignore extra fields as long as 2 fields are present
    • 6th service joins consumers, requires new field => able to add new field without breaking other consumers
  • => give producing service leeway to make certain contract changes without breaking compatibility
  • Situations can arise where we need to make changes that could break compatibility (even if using robustness principle)

L35:

  • as long exposed APIs stay backward compatible => update and deploy independently
    • thanks to loose coupling

L53:

  • Context: name resolution policy between service API and endpoint in API gateway
  • replacement with new version is easy if API is backward compatible in syntax and semantic

L59:

  • Structure of API calls should be stable and backward compatible
    • even if underlying data or schema changes

LN43:

  • Interface of microservices should be simple to use and have good backward compatibility
    • when new functionalities introduced, so that clients do not have to be neccessarily updated

Interview B:

  • API needs to stay downward compatible
    • e.g. add API fields (change structure) without consumers to run into problems
  • 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

Interivew D:

  • Do I version or no?
  • If not, what do I do instead? How to ensure backward compatibility?