NestJS — Enterprise Node.js

Lifecycle Hooks & Application Context

16 min Lesson 18 of 30

Lifecycle Hooks & Application Context

A NestJS application has a life: it boots, runs, and shuts down. Lifecycle hooks let your providers run code at precise moments — opening a database connection after init, or closing it cleanly on shutdown. Used well, they make your app reliable and resource-safe.

The lifecycle sequence

NestJS calls hook methods in a defined order during bootstrap and termination. The most useful are:

  • onModuleInit() — runs once the host module's dependencies are resolved.
  • onApplicationBootstrap() — runs after all modules are initialised.
  • onModuleDestroy() — runs when the app begins shutting down.
  • onApplicationShutdown(signal) — runs last, with the termination signal.

Implementing a hook

Implement the matching interface and the method on a provider:

import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; @Injectable() export class DatabaseService implements OnModuleInit, OnModuleDestroy { async onModuleInit() { await this.connect(); // open the connection at startup console.log('DB connected'); } async onModuleDestroy() { await this.disconnect(); // close it cleanly on shutdown console.log('DB disconnected'); } }
Hooks can be async. NestJS awaits an async onModuleInit() before considering the module ready, so the app will not start serving requests until your initialisation finishes.

Graceful shutdown

Shutdown hooks only fire if you explicitly enable shutdown listeners — this is what lets a container drain in-flight requests and release resources before the process exits:

// main.ts const app = await NestFactory.create(AppModule); app.enableShutdownHooks(); // required for onModuleDestroy / onApplicationShutdown await app.listen(3000);
onApplicationShutdown will NOT run by default. Without app.enableShutdownHooks(), termination signals (SIGTERM/SIGINT) bypass your cleanup. In containerised deployments, forgetting this leaks connections and drops in-flight work.

The standalone application context

Sometimes you want NestJS's DI and providers without an HTTP server — for a CLI command, a cron script, or a one-off task. createApplicationContext() builds exactly that:

import { NestFactory } from '@nestjs/core'; async function runTask() { const app = await NestFactory.createApplicationContext(AppModule); const reportService = app.get(ReportService); // resolve any provider await reportService.generateDaily(); await app.close(); // triggers destroy hooks }
app.get() escapes the controller. The application context lets you pull any provider out of the container and call it directly — perfect for seeders, migrations, and scheduled jobs that reuse your services without an HTTP layer.

Summary

Lifecycle hooks (onModuleInit, onApplicationBootstrap, onModuleDestroy, onApplicationShutdown) let providers run setup and teardown at the right moments; remember app.enableShutdownHooks() for graceful shutdown. The standalone application context (createApplicationContext + app.get()) reuses your DI and services without an HTTP server. Next: architecture patterns that tie all of this together.