How NestJS Boots: Factory Pattern, Module Assembly, and Dependency Injection from Scratch
NestJS is the dominant enterprise Node.js framework for pure backend work—APIs, microservices, and system integration—and its startup sequence reveals the architectural assumptions every production service inherits. Understanding the factory entry point, module assembly, and DI wiring upfront prevents the common confusion where developers treat the scaffold as magic and struggle to debug injection failures or module misconfiguration later.
A NestJS application begins in `main.ts` where `NestFactory.create(AppModule)` acts as a factory, constructing the server without manual instantiation. The root module `AppModule` declares its controllers and services inside a `@Module` decorator, and the framework assembles them at startup. Controllers handle routing and simple logic, while services contain business logic and data access; the two layers connect through constructor-based dependency injection, triggered by `@Injectable()` and the `providers` array.
A Mixue Bingcheng demo illustrates the factory pattern: callers request a product by type from `MixueFactory.create()` and receive an object that implements a common interface, never touching the concrete classes. The same pattern underpins `NestFactory.create()`, which accepts a module class and returns a fully wired application instance.
A traced request to `localhost:3000/` shows the full chain: the HTTP listener forwards to the root module, which routes to `AppController.getHello()`, which delegates to `AppService.getHello()`, and the returned string becomes the response body. The scaffold omits a real database, view layer, and parameter validation, leaving those as the natural next steps beyond the hello-world stage.
The `switch` statement in the factory demo lacks a `default` case, so an unrecognized type returns `undefined` and crashes at runtime—a small omission that mirrors real production bugs when factories don't guard against unknown inputs.
NestJS's dependency injection looks automatic but is brittle: omitting any one of the three required pieces—`providers` entry, `@Injectable()`, or constructor parameter—silently produces `undefined` rather than a clear error, which trips up newcomers who assume the framework will warn them.
The scaffold's MVC claim is aspirational rather than implemented; calling a two-class setup 'MVC' when the Model and View are entirely missing sets an expectation that the framework alone provides structure, when in practice the developer must supply the database layer and response formatting.