What if you could let NestJS handle all your service wiring so you never worry about creating or sharing instances again?
Why Custom providers in NestJS? - Purpose & Use Cases
Imagine you have to manually create and manage every service and dependency in your NestJS app without any help from the framework.
You write new instances everywhere and pass them around yourself.
This manual approach quickly becomes messy and confusing.
You risk creating multiple instances of the same service, making bugs hard to find.
It's also hard to change implementations without rewriting lots of code.
Custom providers let NestJS handle creating and sharing your services automatically.
You define how to create a service once, and NestJS injects the same instance wherever needed.
This keeps your code clean, consistent, and easy to update.
const service = new MyService(); component.use(service);
@Injectable() class MyService {} @Module({ providers: [{ provide: 'MyService', useClass: MyService }] }) export class AppModule {}
Custom providers enable flexible, maintainable, and testable code by letting NestJS manage service creation and sharing.
When you want to swap a logging service with a mock version for testing, custom providers let you do this easily without changing your app code.
Manual service creation is error-prone and hard to maintain.
Custom providers let NestJS manage service instances automatically.
This leads to cleaner, more flexible, and testable applications.
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
