Files
agent-skills/skills/nestjs-best-practices/rules/perf-async-hooks.md
Jason Woltje 861b28b965 feat: Expand fleet to 23 skills across all domains
New skills (14):
- nestjs-best-practices: 40 priority-ranked rules (kadajett)
- fastapi: Pydantic v2, async SQLAlchemy, JWT auth (jezweb)
- architecture-patterns: Clean Architecture, Hexagonal, DDD (wshobson)
- python-performance-optimization: Profiling and optimization (wshobson)
- ai-sdk: Vercel AI SDK streaming and agent patterns (vercel)
- create-agent: Modular agent architecture with OpenRouter (openrouterteam)
- proactive-agent: WAL Protocol, compaction recovery, self-improvement (halthelobster)
- brand-guidelines: Brand identity enforcement (anthropics)
- ui-animation: Motion design with accessibility (mblode)
- marketing-ideas: 139 ideas across 14 categories (coreyhaines31)
- pricing-strategy: SaaS pricing and tier design (coreyhaines31)
- programmatic-seo: SEO at scale with playbooks (coreyhaines31)
- competitor-alternatives: Comparison page architecture (coreyhaines31)
- referral-program: Referral and affiliate programs (coreyhaines31)

README reorganized by domain: Code Quality, Frontend, Backend,
Auth, AI/Agent Building, Marketing, Design, Meta.

Mosaic Stack is not limited to coding — the Orchestrator serves
coding, business, design, marketing, writing, logistics, and analysis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:22:53 -06:00

110 lines
2.8 KiB
Markdown

---
title: Use Async Lifecycle Hooks Correctly
impact: HIGH
impactDescription: Improper async handling blocks application startup
tags: performance, lifecycle, async, hooks
---
## Use Async Lifecycle Hooks Correctly
NestJS lifecycle hooks (`onModuleInit`, `onApplicationBootstrap`, etc.) support async operations. However, misusing them can block application startup or cause race conditions. Understand the lifecycle order and use hooks appropriately.
**Incorrect (fire-and-forget async without await):**
```typescript
// Fire-and-forget async without await
@Injectable()
export class DatabaseService implements OnModuleInit {
onModuleInit() {
// This runs but doesn't block - app starts before DB is ready!
this.connect();
}
private async connect() {
await this.pool.connect();
console.log('Database connected');
}
}
// Heavy blocking operations in constructor
@Injectable()
export class ConfigService {
private config: Config;
constructor() {
// BLOCKS entire module instantiation synchronously
this.config = fs.readFileSync('config.json');
}
}
```
**Correct (return promises from async hooks):**
```typescript
// Return promise from async hooks
@Injectable()
export class DatabaseService implements OnModuleInit {
private pool: Pool;
async onModuleInit(): Promise<void> {
// NestJS waits for this to complete before continuing
await this.pool.connect();
console.log('Database connected');
}
async onModuleDestroy(): Promise<void> {
// Clean up resources on shutdown
await this.pool.end();
console.log('Database disconnected');
}
}
// Use onApplicationBootstrap for cross-module dependencies
@Injectable()
export class CacheWarmerService implements OnApplicationBootstrap {
constructor(
private cache: CacheService,
private products: ProductsService,
) {}
async onApplicationBootstrap(): Promise<void> {
// All modules are initialized, safe to warm cache
const products = await this.products.findPopular();
await this.cache.warmup(products);
}
}
// Heavy init in async hooks, not constructor
@Injectable()
export class ConfigService implements OnModuleInit {
private config: Config;
constructor() {
// Keep constructor synchronous and fast
}
async onModuleInit(): Promise<void> {
// Async loading in lifecycle hook
this.config = await this.loadConfig();
}
private async loadConfig(): Promise<Config> {
const file = await fs.promises.readFile('config.json');
return JSON.parse(file.toString());
}
get<T>(key: string): T {
return this.config[key];
}
}
// Enable shutdown hooks in main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableShutdownHooks(); // Enable SIGTERM/SIGINT handling
await app.listen(3000);
}
```
Reference: [NestJS Lifecycle Events](https://docs.nestjs.com/fundamentals/lifecycle-events)