Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
40 prioritized NestJS best practices across architecture, DI, security, performance, testing, and microservices.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
rules/arch-module-sharing.md
1---2title: Use Proper Module Sharing Patterns3impact: CRITICAL4impactDescription: Prevents duplicate instances, memory leaks, and state inconsistency5tags: architecture, modules, sharing, exports6---78## Use Proper Module Sharing Patterns910NestJS modules are singletons by default. When a service is properly exported from a module and that module is imported elsewhere, the same instance is shared. However, providing a service in multiple modules creates separate instances, leading to memory waste, state inconsistency, and confusing behavior. Always encapsulate services in dedicated modules, export them explicitly, and import the module where needed.1112**Incorrect (service provided in multiple modules):**1314```typescript15// StorageService provided directly in multiple modules - WRONG16// storage.service.ts17@Injectable()18export class StorageService {19private cache = new Map(); // Each instance has separate state!2021store(key: string, value: any) {22this.cache.set(key, value);23}24}2526// app.module.ts27@Module({28providers: [StorageService], // Instance #129controllers: [AppController],30})31export class AppModule {}3233// videos.module.ts34@Module({35providers: [StorageService], // Instance #2 - different from AppModule!36controllers: [VideosController],37})38export class VideosModule {}3940// Problems:41// 1. Two separate StorageService instances exist42// 2. cache.set() in VideosModule doesn't affect AppModule's cache43// 3. Memory wasted on duplicate instances44// 4. Debugging nightmares when state doesn't sync45```4647**Correct (dedicated module with exports):**4849```typescript50// storage/storage.module.ts51@Module({52providers: [StorageService],53exports: [StorageService], // Make available to importers54})55export class StorageModule {}5657// videos/videos.module.ts58@Module({59imports: [StorageModule], // Import the module, not the service60controllers: [VideosController],61providers: [VideosService],62})63export class VideosModule {}6465// channels/channels.module.ts66@Module({67imports: [StorageModule], // Same instance shared68controllers: [ChannelsController],69providers: [ChannelsService],70})71export class ChannelsModule {}7273// app.module.ts74@Module({75imports: [76StorageModule, // Only if AppModule itself needs StorageService77VideosModule,78ChannelsModule,79],80})81export class AppModule {}8283// Now all modules share the SAME StorageService instance84```8586**When to use @Global() (sparingly):**8788```typescript89// ONLY for truly cross-cutting concerns90@Global()91@Module({92providers: [ConfigService, LoggerService],93exports: [ConfigService, LoggerService],94})95export class CoreModule {}9697// Import once in AppModule98@Module({99imports: [CoreModule], // Registered globally, available everywhere100})101export class AppModule {}102103// Other modules don't need to import CoreModule104@Module({105controllers: [UsersController],106providers: [UsersService], // Can inject ConfigService without importing107})108export class UsersModule {}109110// WARNING: Don't make everything global!111// - Hides dependencies (can't see what a module needs from imports)112// - Makes testing harder113// - Reserve for: config, logging, database connections114```115116**Module re-exporting pattern:**117118```typescript119// common.module.ts - shared utilities120@Module({121providers: [DateService, ValidationService],122exports: [DateService, ValidationService],123})124export class CommonModule {}125126// core.module.ts - re-exports common for convenience127@Module({128imports: [CommonModule, DatabaseModule],129exports: [CommonModule, DatabaseModule], // Re-export for consumers130})131export class CoreModule {}132133// feature.module.ts - imports CoreModule, gets both134@Module({135imports: [CoreModule], // Gets CommonModule + DatabaseModule136controllers: [FeatureController],137})138export class FeatureModule {}139```140141Reference: [NestJS Modules](https://docs.nestjs.com/modules#shared-modules)142