Skip to main content
Practice Problems

What are lifecycle hooks in NestJS?

Lifecycle Hooks in NestJS

NestJS provides lifecycle hooks that allow you to execute code at specific points during the application's startup and shutdown sequence. These are essential for initializing connections, starting background tasks, and graceful shutdown.


Available Hooks

Hook InterfaceMethodWhen Called
OnModuleInitonModuleInit()After module's providers are initialized
OnApplicationBootstraponApplicationBootstrap()After all modules initialized, before listening
OnModuleDestroyonModuleDestroy()After app.close() is called
BeforeApplicationShutdownbeforeApplicationShutdown(signal)Before shutdown (receives OS signal)
OnApplicationShutdownonApplicationShutdown(signal)After all connections closed

OnModuleInit — Setup after DI

typescript
import { Injectable, OnModuleInit } from '@nestjs/common'; @Injectable() export class DatabaseService implements OnModuleInit { async onModuleInit() { // Called once after all providers in the module are instantiated await this.connect(); console.log('Database connected'); } private async connect() { // Establish database connection } }

OnApplicationBootstrap — After Full Init

typescript
import { Injectable, OnApplicationBootstrap } from '@nestjs/common'; @Injectable() export class SeedService implements OnApplicationBootstrap { constructor( private readonly usersService: UsersService, private readonly configService: ConfigService, ) {} async onApplicationBootstrap() { if (this.configService.get('NODE_ENV') === 'development') { await this.seedDatabase(); } } private async seedDatabase() { const count = await this.usersService.count(); if (count === 0) { await this.usersService.create({ name: 'Admin', email: 'admin@app.com' }); console.log('Database seeded'); } } }

Graceful Shutdown

typescript
// main.ts — enable shutdown hooks async function bootstrap() { const app = await NestFactory.create(AppModule); app.enableShutdownHooks(); // listen for SIGTERM, SIGINT await app.listen(3000); }
typescript
// services/queue.service.ts import { Injectable, OnApplicationShutdown, BeforeApplicationShutdown } from '@nestjs/common'; @Injectable() export class QueueService implements BeforeApplicationShutdown, OnApplicationShutdown { private isShuttingDown = false; beforeApplicationShutdown(signal: string) { console.log(`Received signal: ${signal}`); this.isShuttingDown = true; // stop accepting new jobs } async onApplicationShutdown(signal: string) { await this.waitForActiveJobs(); await this.closeConnection(); console.log('Queue service shut down gracefully'); } private waitForActiveJobs(): Promise<void> { return new Promise(resolve => setTimeout(resolve, 2000)); } }

OnModuleDestroy — Per-Module Cleanup

typescript
@Injectable() export class CacheService implements OnModuleDestroy { private client: RedisClient; async onModuleDestroy() { await this.client.quit(); console.log('Redis connection closed'); } }

Full Lifecycle Order

1. Modules initialized (providers created) 2. onModuleInit() — per provider 3. onApplicationBootstrap() — per provider 4. app.listen() — server starts accepting requests --- [SIGTERM / app.close()] 5. beforeApplicationShutdown(signal) — per provider 6. Server stops accepting new connections 7. onModuleDestroy() — per provider 8. onApplicationShutdown(signal) — per provider 9. Process exits

Summary

Lifecycle hooks make NestJS services aware of the application lifecycle. Use OnModuleInit for post-DI setup (DB connections, cache warm-up), OnApplicationBootstrap for post-startup tasks (seeding, health checks), and OnApplicationShutdown + app.enableShutdownHooks() for graceful shutdown (draining connections, finishing jobs).

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems