Introduction
Some resources take time to initialize—database connections, remote configuration fetches, or service discovery. NestJS waits for async providers to resolve before starting the application, ensuring dependencies are ready when needed.
Key Concepts
- Async Provider: Provider whose factory returns a Promise
- Application Bootstrap: Process of starting the NestJS app
- Blocking Initialization: App waits for async providers before accepting requests
Real World Context
Consider connecting to a database. You can't serve requests until the connection is established. Async providers ensure the connection is ready before the app starts handling traffic.
Deep Dive
Async Factory Provider
typescriptconst databaseProvider = { provide: 'DATABASE_CONNECTION', useFactory: async (configService: ConfigService) => { const options = configService.get('database'); const connection = await createConnection(options); console.log('Database connected'); return connection; }, inject: [ConfigService], };
With External API
typescriptconst configProvider = { provide: 'REMOTE_CONFIG', useFactory: async () => { const response = await fetch('https://config-server.example.com/app-config'); return response.json(); }, };
Module with Async Configuration
typescript@Module({ imports: [ TypeOrmModule.forRootAsync({ imports: [ConfigModule], useFactory: async (configService: ConfigService) => ({ type: 'postgres', host: configService.get('DB_HOST'), port: configService.get('DB_PORT'), database: configService.get('DB_NAME'), }), inject: [ConfigService], }), ], }) export class AppModule {}
Handling Errors
typescriptconst provider = { provide: 'CRITICAL_SERVICE', useFactory: async () => { try { return await initializeCriticalService(); } catch (error) { console.error('Failed to initialize:', error); throw error; // Prevents app from starting } }, };
Common Pitfalls
- No error handling: Unhandled rejections crash the app. Add try/catch.
- Slow initialization: Long async operations delay startup. Consider timeouts.
- Not logging failures: Silent failures make debugging impossible.
Best Practices
- Add timeouts for external service connections
- Log initialization progress for debugging
- Gracefully handle failures where possible
- Consider health checks after initialization
Summary
Async providers use factory functions returning Promises. NestJS waits for all async providers to resolve before accepting requests. Handle errors gracefully and add timeouts to prevent indefinite startup delays.
Code Examples
typescript
const databaseProvider = {
provide: 'DATABASE_CONNECTION',
useFactory: async (configService: ConfigService) => {
const connection = await createConnection({
host: configService.get('DB_HOST'),
port: configService.get('DB_PORT'),
});
return connection;
},
inject: [ConfigService],
};