MicroservicePatterns.com

Suggestions

  • PagePattern catalogAll patterns by category.
  • LabCircuit Breaker and Retries labCrash a dependency and tune the breaker.
  • LabSaga labFail a step and watch the compensations run.
  • PagePractice questionsScenario questions with explanations.
  • PageDesign reviewCheck your own architecture for anti-patterns.
Frontend · Foundation

Backward-Compatible API Evolution

The Backward-Compatible API Evolution pattern changes an API only by adding to it, and supports old client versions until they are retired on purpose, so apps that are already installed keep working.

Last updated

Use it when

  • You ship mobile, desktop or embedded clients that users update on their own schedule.
  • Third parties or other teams call your API and release independently of you.

Avoid it when

  • The only client is a web app deployed with the API, so both always change together.

What is the Backward-Compatible API Evolution pattern?

A web app is replaced on the next page load, but a mobile app on someone's phone keeps running whatever version they installed. Backward-compatible evolution means every API change works for the clients already out there: new fields are added, existing ones keep their meaning, and anything removed goes through a deprecation period. Clients read responses tolerantly and ignore what they do not understand.

What problem does the Backward-Compatible API Evolution pattern solve?

Renaming a field or making an optional one required breaks every installed app that has not updated, and you cannot force an update the way you redeploy a service. The breakage shows up as crashes in app store reviews, often days later. Treating installed clients as consumers you cannot change keeps one backend release from breaking millions of phones.

How do you implement the Backward-Compatible API Evolution pattern?

  1. Only add to responses and requests. Never rename, retype or remove a field that a released client reads.
  2. Have clients ignore unknown fields and enum values, and fall back sensibly when an optional field is missing.
  3. Send the app version with every request and record which versions are still in use.
  4. When a breaking change is unavoidable, serve both shapes side by side, for example a new endpoint or version, until usage of the old one falls below an agreed level.
  5. Keep a minimum supported version the backend can return, so very old apps show an upgrade screen instead of failing.

When should you use it?

  • You ship mobile, desktop or embedded clients that users update on their own schedule.
  • Third parties or other teams call your API and release independently of you.

When should you avoid it?

  • The only client is a web app deployed with the API, so both always change together.

What do you gain?

  • Backend releases do not break installed apps
  • Client and server teams release independently
  • Old versions are retired on purpose, with data on who is affected

What does it cost?

  • Old fields and endpoints linger and need maintenance
  • More versions to test
  • Forced upgrades annoy users and need a careful message

Who usually owns the Backward-Compatible API Evolution pattern?

Product teams. Each product team applies this in the services, screens and data it owns. The platform may offer templates or examples, but the design decisions belong to the team. See how teams map to layers and patterns.

What are common mistakes with the Backward-Compatible API Evolution pattern?

  • A strict JSON parser in the app that crashes on an unknown enum value the backend just added.
  • Removing a field because the latest app no longer reads it, while older versions still do.
  • No version data, so nobody knows whether it is safe to turn an old endpoint off.

Backward-Compatible API Evolution in practice

Real-world example

Stripe

Stripe's API is built into its customers' own code, and those integrations cannot all change every time the API does.

Stripe names API versions by release date and pins each account to the newest version on its first request. When it responds, the API starts from the current version and applies version change modules backwards until it reaches the version the caller expects. In 2017 Stripe wrote that this had covered almost a hundred backwards-incompatible changes while keeping every version since 2011 working.

Source: APIs as infrastructure: future-proofing Stripe with versioning (Stripe, 2017)

Example decision record
Context
A third of mobile users run app versions more than two months old, and a backend field rename has just broken them.
Decision
Treat every released API as add-only, send the app version on every request, and remove fields only when old versions fall below an agreed share of traffic.
Consequences
  • Backend releases no longer break installed apps.
  • Old fields stay around longer and need a scheduled clean-up.

Test yourself on Backward-Compatible API Evolution

Frontendfoundation

The backend renames 'deliveryDate' to 'estimatedDelivery' in the order API and the new app release reads the new name. A week later, crash reports spike from users who have not updated. What should the team have done?

6 questions involve this pattern. Practice all of them →

Done with Backward-Compatible API Evolution?

Saved in this browser only. See your progress →