API Versioning
- REST API
- HTTP
- Node.js
Evolving an API without breaking existing clients by serving multiple versions, so a breaking change ships as a new version rather than in place.
Prerequisites
- REST API basics (see Related Topics)
What you'll understand
- Why APIs need versioning once they have real clients
- The difference between breaking and non-breaking changes
- Common ways to express an API version
Explanation
API versioning is how you change an API over time without breaking the clients already using it. Once other applications depend on your endpoints, you no longer control when they update. A change that removes a field, renames one, or alters a response shape can break every existing client the moment you deploy it. Versioning gives you a way to introduce such changes safely.
The key distinction is between non-breaking and breaking changes. Adding a new optional field or a new endpoint is non-breaking: existing clients keep working, so it needs no new version. Removing or renaming a field, changing a type, or altering behaviour is breaking, and that is what a new version is for. You ship the breaking change as v2 while v1 continues to serve existing clients until they migrate.
A version is usually expressed in the URL path (/v1/users, /v2/users), which is simple and visible, though it can also live in a header. Whichever you choose, keep it consistent across the whole API, and pair a new version with a deprecation plan: communicate the timeline, and give clients time to move before the old version is retired.
Examples
URL-path versioning keeps both versions available while clients migrate:
GET /v1/users/42 // original response shape
GET /v2/users/42 // new shape with a breaking changeIn NestJS, versioning can be enabled and applied per controller:
app.enableVersioning({ type: VersioningType.URI });
@Controller({ path: 'users', version: '2' })
class UsersV2Controller {}Common mistakes
- Shipping a breaking change into an existing version and breaking live clients.
- Versioning inconsistently, so some endpoints are versioned and others are not.
- Creating a new version for changes that are actually backward-compatible.
- Introducing a new version with no plan to deprecate and retire the old one.
Best practices
- Only bump the version for genuinely breaking changes; add non-breaking changes in place.
- Choose one versioning scheme and apply it across the whole API.
- Keep the previous version running while clients migrate.
- Publish a clear deprecation timeline for retired versions.
Further reading
- NestJS, Versioning — https://docs.nestjs.com/techniques/versioning
- Microsoft, Web API design best practices — https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design