NestJS Architecture Expert
Priority: P0 (CRITICAL)
Design feature modules with singleton-first providers and explicit request-pipeline choices.
Decision Map
- Module role: Feature Modules (Auth) vs Core (Config/DB) vs Shared (Utils). Feature owns its controllers, application services, and adapters. Shared exports stateless helpers only.
- Provider scope: default singleton. Use request scope only for tenant context, request-local caching, or request tracking. Treat request scope as a measured exception.
- Pipeline choice: middleware for raw HTTP concerns, guard for access decisions, pipe for validation/transforms, interceptor for cross-cutting request/response behavior, filter for error translation.
Recipe
- Create bounded feature: module + controller + application service + persistence adapter.
- Keep controller thin: Thin controllers, fat services. No business in Controller. Move logic to Service.
- Register dependencies once: imports for modules, providers for services, exports only for true consumers.
@InjectRepository()dependencies needTypeOrmModule.forFeature([...]). - Validate at edges: DTO validation pipes for incoming data; never trust raw payloads in services.
- Check circular imports: check circular dependencies with
madge; refactor contracts first and useforwardRef()only as last resort.
Verify
- [ ] Feature module owns one business capability, not a mixed grab bag.
- [ ] Providers are singleton unless request scope has a written reason.
- [ ] Guard/pipe/interceptor/filter placement matches the request lifecycle.
- [ ] Config uses
@nestjs/configor a typed config layer, not scatteredprocess.env. - [ ] Dependency Integrity: DB repositories, queues, and clients are registered in the module graph, not manually instantiated.
Anti-Patterns
- No request scope by default: Singleton first; justify heavier scope.
- No business logic in controllers: Delegate orchestration to services/use cases.
- No entity leakage: Don't return ORM entities; return DTOs or response models.
- No manual instantiation: Use DI; never
new Service()inside Nest code.