Custom providers let you tell NestJS how to create or find a value or service. This helps you control what your app uses in different places.
Custom providers in NestJS
providers: [
{
provide: TOKEN_OR_CLASS,
useClass: ClassToUse,
},
{
provide: TOKEN_OR_CLASS,
useValue: someValue,
},
{
provide: TOKEN_OR_CLASS,
useFactory: () => {
return new SomeClass();
},
},
{
provide: TOKEN_OR_CLASS,
useExisting: ExistingProvider,
}
]provide is the token or class name NestJS uses to find this provider.
You can use useClass, useValue, useFactory, or useExisting to tell NestJS how to get the value.
providers: [
{
provide: 'MY_VALUE',
useValue: 42,
}
]MyCustomService whenever MyService is requested.providers: [
{
provide: MyService,
useClass: MyCustomService,
}
]providers: [
{
provide: 'CONFIG',
useFactory: () => ({
host: 'localhost',
port: 3000,
}),
}
]ExistingService.providers: [
ExistingService,
{
provide: 'ALIAS',
useExisting: ExistingService,
}
]This example shows how to create a custom provider named 'Logger' that uses CustomLoggerService instead of the default LoggerService. The AppService asks for 'Logger' and gets the custom version. When run() is called, it logs with the custom prefix.
import { Injectable, Module, Inject } from '@nestjs/common'; @Injectable() class LoggerService { log(message: string) { console.log('LOG:', message); } } @Injectable() class CustomLoggerService { log(message: string) { console.log('CUSTOM LOG:', message); } } @Injectable() class AppService { constructor(@Inject('Logger') private logger: LoggerService) {} run() { this.logger.log('App is running'); } } @Module({ providers: [ AppService, { provide: 'Logger', useClass: CustomLoggerService, }, ], }) export class AppModule {} // Simulate NestJS bootstrap and usage async function bootstrap() { // Manually create instances to simulate NestJS DI const logger = new CustomLoggerService(); const appService = new AppService(logger); appService.run(); } bootstrap();
Custom providers let you swap implementations without changing the code that uses them.
Use useValue for simple constants, useClass for classes, useFactory for dynamic creation, and useExisting to alias providers.
Always provide a unique token or class in provide to avoid conflicts.
Custom providers control how NestJS creates or finds a service or value.
You can provide classes, values, factories, or aliases using different keys.
This helps make your app flexible and easy to test.
Practice
custom provider in NestJS?Solution
Step 1: Understand the role of providers in NestJS
Providers are responsible for creating and managing services or values that can be injected into other parts of the app.Step 2: Identify what custom providers do
Custom providers let you control exactly how NestJS creates or finds these services or values, making your app more flexible.Final Answer:
To control how NestJS creates or finds a service or value -> Option CQuick Check:
Custom provider purpose = control creation/finding [OK]
- Confusing providers with routing or middleware
- Thinking providers manage database or auth directly
- Assuming providers only register classes, not values or factories
Solution
Step 1: Recall the syntax for value providers
Value providers use theuseValuekey to assign a fixed value to a token.Step 2: Check each option's correctness
{ provide: 'API_URL', useValue: 'https://api.example.com' } correctly usesuseValuewith a string value. Other options misuseuseClass,useFactory, oruseExistingwhich expect different types.Final Answer:
{ provide: 'API_URL', useValue: 'https://api.example.com' } -> Option AQuick Check:
Value provider uses useValue = { provide: 'API_URL', useValue: 'https://api.example.com' } [OK]
- Using useClass or useFactory for fixed values
- Confusing useExisting with useValue
- Putting string directly without useValue
{ provide: 'RANDOM_NUMBER', useFactory: () => Math.floor(Math.random() * 10) }
What will be the output if you inject 'RANDOM_NUMBER' twice in the same request?Solution
Step 1: Understand provider scope and factory behavior
By default, NestJS providers are singletons per application context, so the factory runs once and the result is reused.Step 2: Analyze injection behavior
Injecting 'RANDOM_NUMBER' twice in the same request returns the same value because the factory was called once at provider creation.Final Answer:
The same random number both times -> Option AQuick Check:
Singleton factory = same value injected [OK]
- Assuming factory runs on every injection
- Thinking useFactory causes errors without async
- Believing random number changes per injection
{ provide: 'CONFIG', useFactory: () => ({ port: 3000 }) }
If you want to inject this provider but get an error "Nest can't resolve dependencies", what is the most likely cause?Solution
Step 1: Check provider registration
For NestJS to inject a provider, it must be registered in the module'sprovidersarray.Step 2: Evaluate other options
useFactory can be sync or async, tokens can be strings, and useFactory can return objects. The error usually means the provider is not registered.Final Answer:
The provider is missing from the module's providers array -> Option DQuick Check:
Missing provider registration = injection error [OK]
- Assuming useFactory must be async
- Thinking tokens must be classes only
- Believing useFactory can't return objects
Solution
Step 1: Understand dynamic value creation
To choose a value based on environment variables at runtime, a factory provider is ideal because it runs code to decide the value.Step 2: Evaluate each option
{ provide: 'DB_CONNECTION', useFactory: () => process.env.NODE_ENV === 'prod' ? 'prod-db' : 'dev-db' } usesuseFactorywith a function that returns the correct string based onprocess.env.NODE_ENV. { provide: 'DB_CONNECTION', useValue: process.env.NODE_ENV === 'prod' ? 'prod-db' : 'dev-db' } usesuseValuewhich is static at module load time. Options C and D misuseuseClassanduseExistingwith strings or conditions incorrectly.Final Answer:
{ provide: 'DB_CONNECTION', useFactory: () => process.env.NODE_ENV === 'prod' ? 'prod-db' : 'dev-db' } -> Option BQuick Check:
Dynamic values need useFactory with runtime logic [OK]
- Using useValue for dynamic environment-based values
- Misusing useClass or useExisting with strings
- Expecting useFactory to be static
Ready to prove it?
Pass the test and this pattern moves unknown
