API Versioning
Enable versioning so multiple versions of a route can coexist without breaking clients.
app.enableVersioning({ type: VersioningType.URI })As an API evolves you need to change endpoints without breaking existing clients. Nest has built-in versioning.
Enable it
Call app.enableVersioning() in main.ts, choosing a strategy - URI (e.g. /v1/users), header, or media type. Then set a version on a controller or route with the version option or @Version().
URI versioning is the most common and visible choice.
Example
import { NestFactory } from '@nestjs/core';
import { VersioningType } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableVersioning({ type: VersioningType.URI });
await app.listen(3000);
}
bootstrap();
// @Controller({ path: 'users', version: '1' }) -> /v1/usersWhen to use it
- A team enables URI versioning so /v1/users and /v2/users can coexist while the V2 controller introduces breaking changes without affecting existing clients.
- A developer marks only one controller method with @Version("2") to upgrade a single endpoint while the rest of the controller stays on V1.
- An engineer sets a defaultVersion so clients that do not specify a version in the URL are served by the default version automatically.
More examples
Enable URI versioning in main.ts
Enables URI-based versioning globally with /v1 as the default so unversioned routes fall back to V1.
import { VersioningType } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableVersioning({
type: VersioningType.URI, // /v1/..., /v2/...
defaultVersion: '1',
});
await app.listen(3000);
}Controller-level versioning
Shows two controllers for the same path but different versions, allowing breaking changes to coexist without a single controller growing too large.
import { Controller, Get, Version } from '@nestjs/common';
@Controller({ path: 'users', version: '1' }) // handles /v1/users
export class UsersV1Controller {
@Get() findAll() { return [{ v: 1 }]; }
}
@Controller({ path: 'users', version: '2' }) // handles /v2/users
export class UsersV2Controller {
@Get() findAll() { return [{ v: 2, extra: true }]; }
}Method-level version override
Overrides the version on a single method with @Version("2") so only that endpoint is upgraded to V2 within a V1 controller.
import { Controller, Get, Version } from '@nestjs/common';
@Controller({ path: 'products', version: '1' })
export class ProductsController {
@Get()
findAllV1() { return []; } // GET /v1/products
@Version('2')
@Get()
findAllV2() { return [{ new: true }]; } // GET /v2/products
}
Discussion