Module encapsulation in NestJS is the principle that providers registered in a module are scoped to that module unless explicitly exported. Directly registering the same provider (e.g., CatsService) in multiple modules creates separate instances per module, increasing memory usage and potentially causing state inconsistency.
The correct approach: encapsulate the provider in a module, export it, and have other modules import that module. This ensures a single shared instance via NestJS’s dependency injection container — a key benefit of modularity:
// ❌ Separate instances per module
@Module({ providers: [CatsService] }) class ModuleA {}
@Module({ providers: [CatsService] }) class ModuleB {}
// ✅ Single shared instance
@Module({ providers: [CatsService], exports: [CatsService] }) class CatsModule {}
@Module({ imports: [CatsModule] }) class ModuleA {}
@Module({ imports: [CatsModule] }) class ModuleB {}