What is a provider?
A Provider in NestJS is any class that can be injected into other classes via the Dependency Injection (DI) system. Put simply, a provider is something that supplies functionality or data, usable by other components (controllers, services, guards, pipes, etc.).
The core idea
A provider is an object that NestJS creates and manages. Nest itself decides:
- when to create the provider's instance;
- how to inject it into the classes that need it;
- how many copies should exist (a singleton, one shared instance, by default).
A simple provider example
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
private users = [{ id: 1, name: 'John' }];
findAll() {
return this.users;
}
}This UsersService is a provider, because it's marked with the @Injectable() decorator.
It can be injected into a controller or another service:
import { Controller, Get } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
getUsers() {
return this.usersService.findAll();
}
}How NestJS creates and injects providers
- Every provider is registered in
@Module()(underproviders). - NestJS puts all providers into the DI container (IoC container).
- When another class declares a dependency in its constructor, NestJS automatically finds and injects the right instance.
Types of providers
| Provider type | Example | Description |
|---|---|---|
| Class provider | @Injectable() class UsersService {} | The most common type |
| Value provider | { provide: 'CONFIG', useValue: { port: 3000 } } | Returns a plain value or object |
| Factory provider | { provide: 'TOKEN', useFactory: () => new Date() } | Creates a value dynamically via a function |
| Alias provider | { provide: 'Alias', useExisting: UsersService } | Points to an already-existing provider |
| Custom-class provider | { provide: 'Logger', useClass: CustomLogger } | Lets you swap a class's implementation |
Examples of different providers
useValue
@Module({
providers: [
{ provide: 'API_KEY', useValue: '12345' },
],
})
export class AppModule {}Injection:
@Injectable()
export class SomeService {
constructor(@Inject('API_KEY') private apiKey: string) {}
}useFactory
@Module({
providers: [
{
provide: 'RANDOM_NUMBER',
useFactory: () => Math.random(),
},
],
})
export class AppModule {}useClass
@Injectable()
class DefaultLogger {
log(msg: string) {
console.log('[Default]', msg);
}
}
@Injectable()
class CustomLogger {
log(msg: string) {
console.log('[Custom]', msg);
}
}
@Module({
providers: [
{ provide: DefaultLogger, useClass: CustomLogger },
],
})
export class AppModule {}Now anywhere DefaultLogger is requested, CustomLogger is used instead.
Providers and Scope
By default a provider is a singleton, but its scope can be changed:
@Injectable({ scope: Scope.REQUEST })
export class RequestScopedService {
// created fresh for every HTTP request
}| Scope | Description |
|---|---|
| Default (Singleton) | One instance for the whole application |
| Request | A new instance for every request |
| Transient | A new instance for every use |
Where providers get registered
Usually inside a module:
@Module({
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}To use UsersService in another module:
@Module({
imports: [UsersModule],
})
export class AuthModule {}Summary
| Concept | Description |
|---|---|
| Provider | A class or value managed by NestJS's DI container |
| Purpose | Supplying functionality, logic, or data to other parts of the app |
| Main tool | @Injectable() and the Dependency Injection system |
| Registered | Under a module's providers |
| Types | useClass, useValue, useFactory, useExisting |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.