API Versioning

Enable versioning so multiple versions of a route can coexist without breaking clients.

Syntaxapp.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

Example · typescript
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/users

When 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.

Example · ts
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.

Example · ts
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.

Example · ts
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

  • Be the first to comment on this lesson.