NestJS is a fantastic framework, but its flexibility can become a trap if strict rules are not followed, leading to architecture drift.
In this article, we'll see how to structure a Node.js application capable of scaling from a few thousand to several million users.
The 3 Pillars
- Modularity: Each feature is an isolated module, free from circular dependencies.
- Independence: The domain should not depend on the framework.
- Observability: Clear logs and distributed tracing.
1. Folder Structure
Instead of grouping by type (controllers, services), group by domain:
src/
modules/
auth/
dto/
entities/
auth.controller.ts
auth.service.ts
auth.module.ts
users/
payments/
2. Hexagonal Architecture
The idea is to separate your business core (the domain) from the infrastructure (database, external APIs).
The domain should never import anything from
@nestjs/common.
This is a golden rule to keep your code testable and sustainable.
Conclusion
A good architecture requires more effort at the start, but saves you months of maintenance later on.
Related Articles
Microservices vs Monolith: How to Actually See Your Architecture
Monolith or microservices? The real question is: can you see what you actually have? Learn how to visualize, compare, and decide with confidence.
Continue readingHow to Detect Circular Dependencies in Your TypeScript Project (and Fix Them)
Learn 3 practical methods to detect circular dependencies in TypeScript: madge CLI, ESLint import/no-cycle, and automated PR checks with ReposLens. Includes fix patterns.
Continue readingMonorepo Dependency Management: Visualize Before It's Too Late
Learn how to manage internal dependencies in a monorepo. Discover common pitfalls like circular deps and god packages, and tools to visualize your architecture.
Continue reading