nestjs-architecture
Module organization, Dependency Injection patterns, and Project Structure.
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
NestJS Architecture Standards
Priority: P0 (FOUNDATIONAL)
Core architectural patterns and dependency injection standards for scalable NestJS applications.
Core Principles
-
Modularity: Every feature must be encapsulated in its own
@Module.-
Do:
users.module.ts,auth.module.ts. -
Don't: Everything in
app.module.ts.
-
Do:
-
Dependency Injection (DI): Invert control. Never manually instantiate classes (e.g.,
new Service()).-
Use: Constructor injection
constructor(private readonly service: Service).
-
Use: Constructor injection
- Scalability: Use Feature Modules for domain logic and Core/Shared Modules for reusable utilities.
Module Configuration
Dynamic Modules
-
Modern Pattern: Use
ConfigurableModuleBuilderclass to auto-generateforRoot/registermethods properly. -
Reference: See Dynamic Module Builder Implementation for the boilerplate code.
-
Conventions:
-
forRoot: Global configurations (Db, Config). -
register: Per-instance configurations. -
forFeature: Extending a module with specific providers/entities.
-
-
Conventions:
Circular Dependencies
- Avoid: Re-architect to move shared logic to a common module.
-
Constraint: If unavoidable, use
forwardRef(() => ModuleName)on both sides of the import.
Advanced Providers
-
Factory Providers: Use
useFactoryheavily for providers dependent on configuration or async operations. -
Aliasing: Use
useExistingto provide backward compatibility or abstract different implementations.
Scopes & Lifecycle
- Default: Singleton. Best performance.
-
Request Scope: Use
Scope.REQUESTsparingly.- Performance Warning: Request scope bubbles up. If a Service is request-scoped, every controller injecting it becomes request-scoped, triggering re-instantiation per request (~5-10% latency overhead).
-
Multi-tenancy: If request-scope is needed (e.g. Tenant ID header), use Durable Providers (
durable: true) withContextIdFactoryto reuse DI sub-trees. -
Shutdown:
SIGTERMdoesn't trigger cleanup by default.-
Mandatory: Call
app.enableShutdownHooks()inmain.ts.
-
Mandatory: Call
Structure & Organization
-
Feature Modules: Domain logic (
ShopModule,AuthModule). Encapsulated. -
Shared Module: Reusable providers (
DateService,MathService) exported to other modules. Stateless. -
Core Module:
- Role: Global infrastructure setup ONE TIME (Interceptors, Filters, Loggers).
-
Rule: Import
CoreModuleonly inAppModule. -
Contents:
APP_INTERCEPTOR,APP_FILTER,APP_GUARDproviders.
Reliability & Observability
-
Health Checks: Mandatory for K8s/Docker.
-
Tool: Use
@nestjs/terminus. Expose/healthendpoint checking DB, Cache (Redis), and Memory.
-
Tool: Use
-
Structured Logging:
- Warning: Default NestJS logger is unstructured text.
-
Standard: Use
nestjs-pinofor JSON-formatted logs with automaticreq-idcorrelation and request duration tracking. -
Context: Inject
Loggerinto services to keep traces connected.
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!