NestJS supports multiple ways to define providers beyond standard classes: plain values, synchronous factories, and asynchronous factories.

Value providers

Use plain values as providers:

{
  provide: 'API_KEY',
  useValue: 'secret-api-key-123',
}

Class providers

Use existing classes as providers:

{
  provide: 'LOGGER',
  useClass: LoggerService,
}

Factory providers (synchronous)

Create providers dynamically with synchronous logic:

{
  provide: 'CONFIG',
  useFactory: (options: Options) => {
    return new ConfigService(options);
  },
  inject: ['OPTIONS'],
}

Factory providers (asynchronous)

Create providers asynchronously (e.g., from database or API):

{
  provide: 'ASYNC_CONFIG',
  useFactory: async () => {
    const config = await fetchConfigFromApi();
    return new ConfigService(config);
  },
}

The FactoryProvider Pattern used in Using Redis Client in NestJS is an example of using factory providers to instantiate ioredis clients with custom configuration.