Custom Providers

Use useValue, useClass, and useFactory to control exactly how a provider is created.

Syntax{ provide: TOKEN, useValue | useClass | useFactory }

The shorthand providers: [UsersService] is the common case. Sometimes you need more control over how an instance is produced. Nest offers custom provider syntax.

The three forms

  • useClass - provide a different class for a token, useful for swapping implementations.
  • useValue - provide a ready-made object or constant, great for config or mocks.
  • useFactory - run a function to build the instance, optionally injecting other providers.

Each custom provider has a provide token (often a class or a string) that consumers request.

Example

Example Β· typescript
import { Module } from '@nestjs/common';

const API_KEY = 'API_KEY';

@Module({
  providers: [
    // useValue: a constant
    { provide: API_KEY, useValue: 'secret-123' },

    // useFactory: build with logic
    {
      provide: 'CONFIG',
      useFactory: () => ({ env: process.env.NODE_ENV ?? 'dev' }),
    },
  ],
})
export class CoreModule {}

When to use it

  • A developer uses useValue to inject a pre-configured third-party client (e.g., an Axios instance) under a custom token.
  • A team uses useFactory with async to create a database connection provider that awaits the connection before the app boots.
  • An architect uses useClass to swap a concrete implementation for an environment-specific alternative (e.g., MockEmailService in tests, SmtpEmailService in production).

More examples

useValue custom provider

Registers a plain object under a string token using useValue so it can be injected with @Inject("APP_CONFIG").

Example Β· ts
import { Module } from '@nestjs/common';

const configProvider = {
  provide: 'APP_CONFIG',
  useValue: { apiUrl: 'https://api.example.com', timeout: 5000 },
};

@Module({ providers: [configProvider] })
export class AppModule {}

useFactory async provider

Uses useFactory with inject to build an async provider that resolves its dependencies and performs async setup before the app starts.

Example Β· ts
import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

@Module({
  providers: [
    {
      provide: 'DB_CONNECTION',
      inject: [ConfigService],
      useFactory: async (cfg: ConfigService) => {
        const url = cfg.get('DATABASE_URL');
        return connectToDatabase(url);  // async setup
      },
    },
  ],
})
export class DatabaseModule {}

useClass environment swap

Swaps the real MailService for a MockMailService in test environments using useClass without changing any injection sites.

Example Β· ts
import { Module } from '@nestjs/common';
import { MailService } from './mail.service';
import { MockMailService } from './mock-mail.service';

@Module({
  providers: [
    {
      provide: MailService,
      useClass: process.env.NODE_ENV === 'test'
        ? MockMailService
        : MailService,
    },
  ],
})
export class MailModule {}

Discussion

  • Be the first to comment on this lesson.