API Versioning & Backwards Compatibility
The problem
An API's shape inevitably needs to change over time, but existing clients — sometimes ones you don't control and can't force to update — depend on its current shape staying stable, so a change that breaks them silently is a real production incident, not a harmless refactor.
Why now
REST API design established a stable, learnable contract as the whole point of good API design; versioning and backwards compatibility are what protect that contract's stability over time, once real clients depend on it and the design inevitably needs to evolve anyway.
Mental model
An API is a promise to existing callers, not just a description of current behavior — a breaking change is any change that would make a correct, unmodified existing client start failing. Versioning is how you keep an old promise (v1) alive unchanged while making and eventually promoting a new one (v2), rather than breaking the old promise out from under whoever's still relying on it.
Requires
- REST API DesignBackend Engineering
Versioning strategy (URL-based, header-based) is layered directly onto the resource/method structure REST already establishes; you need a stable API shape as the thing being versioned before versioning strategy is meaningful.
Used in
- Public APIs (Stripe, GitHub) with explicit, long-lived version numbers in their URLs or headers
- Deprecation policies giving clients a defined window to migrate off an old API version
- Additive-only change strategies (adding optional fields, never removing existing ones) as an alternative to formal versioning
- Mobile app APIs, where old app versions in the wild may never update, forcing long-term backwards compatibility
Projects
- Take an existing API and make a genuinely breaking change (renaming a field) two ways — as a hard break, and properly versioned (/v2/) alongside the still-working /v1/ — and compare the impact on existing clients
- Write a deprecation plan for an API endpoint, including a timeline and how clients would be notified
Examples
- Renaming a JSON field from user_name to username breaks every client parsing the old field, unless done behind a new API version
- Adding a new optional field to a response is backwards compatible; removing or renaming an existing field never is
Resources
Mastery checklist
- I can distinguish a breaking change from a backwards-compatible one
- I can implement at least one API versioning strategy (URL or header-based)
- I can write a reasonable deprecation timeline for retiring an old API version
- I can design a new feature to be added in a backwards-compatible, additive way