NestJS Custom Providers
Not every provider is a simple class listed by name. Custom providers let you bind tokens to values, factories, and alternate classes—essential for config, mocking, and interfaces.
Provider Recipes Nest supports several provider shapes: useClass (alias a token to a class), useValue (provide a constant), useFactory (compute a value with injected deps), and useExisting (create an alias). Tokens can be classes, strings, or symbols.
{
provide: 'API_KEY',
useValue: process.env.API_KEY,
}
{
provide: PaymentsClient,
useFactory: (config: ConfigService) => new PaymentsClient(config.get('PAYMENTS_KEY')),
inject: [ConfigService],
} Factories run inside the DI container, so they can inject ConfigService or other providers before constructing the value.
Injecting a Custom Token constructor(@Inject('API_KEY') private apiKey: string) {} Class tokens inject without @Inject; string/symbol tokens require @Inject(token). useFactory can be async; Nest awaits it during bootstrap. Custom providers are listed in the module providers array like normal classes. Export custom providers if other modules need them. Custom Provider Cheatsheet Common provider object shapes.
Shape When to Use useClass Swap interface token for implementation useValue Constants, mocks, config objects useFactory Construct with injected dependencies useExisting Alias one provider to another token Scope.REQUEST Per-request instance when needed
Interface Tokens TypeScript interfaces disappear at runtime, so use an abstract class or a string/symbol token for interface-based injection.
export const HASHING_SERVICE = Symbol('HASHING_SERVICE');
{ provide: HASHING_SERVICE, useClass: BcryptHashingService } Custom Providers in Tests useValue: mockService in TestingModule is the fastest way to stub dependencies without spinning real infrastructure.
Common Mistakes Forgetting @Inject('TOKEN') for non-class tokens. Omitting inject: [...] on a factory that needs dependencies. Using useValue for something that should be constructed per request. Not exporting a custom provider that other modules try to inject. Key Takeaways Custom providers bind tokens to values, classes, or factories. String/symbol tokens require @Inject. Factories enable config-driven construction during bootstrap. Tests heavily rely on useValue mocks.
Pro Tip
Prefer Symbol('NAME') tokens over magic strings for shared libraries to avoid accidental collisions across packages.
NestJS Environment Variables Go to next item