Application Architecture Patterns
Application Architecture Patterns
NestJS gives you building blocks; architecture is how you arrange them as the app grows. A small project is fine with the default structure, but a large one benefits from clear layers and boundaries. This lesson surveys the patterns that keep big NestJS codebases maintainable.
The default: layered architecture
The structure NestJS encourages out of the box is a layered (N-tier) design, where each layer has one responsibility and depends only on the layer below:
A request flows down the layers and the response flows back up. The golden rule: a controller never touches the database directly, and a repository never contains business rules.
Modular (feature-based) organisation
Within those layers, organise by feature, not by type. Each feature module is a self-contained slice:
This makes features easy to find, easy to test in isolation, and easy to extract into a microservice later if needed.
Clean / hexagonal architecture
For complex domains, teams push further with clean architecture: the business domain sits at the centre and knows nothing about frameworks or databases. Outer layers (controllers, repositories) depend inward on abstractions, never the other way around:
- Domain — entities and business rules, pure and framework-free.
- Application — use cases that orchestrate the domain.
- Infrastructure — database, HTTP, external services (the replaceable details).
NestJS's dependency injection makes this natural: a service depends on an interface (a token), and you bind the concrete database implementation via a custom provider — so the domain never imports the ORM.
Practical guidelines
- Keep controllers thin: validate, delegate, return.
- Put business logic in services; put data access behind a repository.
- Organise by feature module; export only what other modules need.
- Depend on abstractions (tokens/interfaces) for things you may swap.
- Do not over-engineer — add layers when complexity demands them, not before.
Summary
NestJS defaults to a layered architecture (controller → service → repository) organised into feature modules. As complexity grows, clean/hexagonal architecture keeps the business domain independent of frameworks and databases, which NestJS's DI supports naturally through interface tokens and custom providers. Choose the lightest structure that fits the problem. This completes Phase 4 — your apps are now well-configured and well-structured. Next: the data layer.