mrkeyoor.com_
Sat 19 Sept 06:45 UTC
npmWeb Backendupdated 19 Sept 2026

@nestjs/core review

`@nestjs/core` 11.2.3 contains Nest's module scanner, dependency-injection container, application factory, and request pipeline. It connects controllers and providers to an Express or Fastify adapter; installing core alone does not create a usable HTTP server. The 11.2 line adds HTTP `QUERY` handling, better singleton sharing and discovery for lazy modules, and an abort signal for server-sent event producers. Patch 11.2.1 repaired an early SSE return, 11.2.2 fixed startup failures around instrumentation and proxy providers, and 11.2.3 fixes circular durable providers. The package remains CommonJS, bundles TypeScript declarations, and requires Node 20 or newer.

Verdict

Our `@nestjs/core` 11.2.1 install took 8.8 seconds, left 27 packages and 17 MB, passed npm audit, and failed a browser build because this is Node-only infrastructure. Adopt the current 11.2.3 package for a backend that needs Nest's container and module rules; a small route set is cheaper to own in Fastify, Express, or Hono.

We installed it

Lab card: what happened when we installed @nestjs/coreScreenshot of @nestjs/core documentation
Install✓ · 8.8s27 packages on disk · 17 MB
ImportESM import works · require() works · CommonJS package
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @nestjs/core install cleanly?

Yes. In a fresh container with an empty cache, npm install @nestjs/core finished in 9 seconds, leaving 27 packages and 17 MB on disk. npm audit reported no known vulnerabilities.

Can @nestjs/core run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does @nestjs/core work with both ESM and CommonJS?

Yes. Both import '@nestjs/core' and require('@nestjs/core') worked in Node 22 in our run. The package is published as CommonJS.

Does @nestjs/core include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@nestjs/core or fastify: which should you use?

fastify: Pick it for schema-aware HTTP handling when the team wants to choose its own architecture. Our @nestjs/core 11.2.1 install took 8.8 seconds, left 27 packages and 17 MB, passed npm audit, and failed a browser build because this is Node-only infrastructure.

When should you not use @nestjs/core?

A service has only a handful of routes. Modules, providers, DTO classes, decorators, and bootstrap code can cost more than direct Fastify or Express handlers.

API stability4/5Modules, controllers, injectable providers, `NestFactory`, guards, pipes, interceptors, and filters still define the public programming model in 11.2.3. Recent patches changed lazy loading, SSE cancellation, instrumentation startup, and circular durable providers without discarding those concepts. Major releases can reach below core: Nest 11 raised the Node floor to 20 and adopted Express 5 behavior, so route matching and middleware deserve migration tests.
Docs5/5Nest's official manual gives separate, linked guides for fundamentals, testing, security, WebSockets, GraphQL, microservices, and operational techniques. Code examples consistently locate behavior in a module, controller, provider, or bootstrap file, which makes a large framework navigable. Adapter-specific request methods and middleware compatibility still send readers to Express or Fastify documentation, and package-version details require checking the migration guide alongside topical pages.
Maintenance5/5The current 11.2.3 patch shipped on 2026-08-25 and the monorepo was pushed on 2026-08-26. Two patches on August 25 repaired instrumentation startup, proxy-provider startup, and circular durable-provider resolution after 11.2.1's SSE fix. GitHub reports 20 open issues and pull requests combined. That quick corrective cadence is reassuring, though it also argues for pinning coordinated Nest packages and testing startup before automatic upgrades.
Ecosystem5/5The package recorded 14,182,142 npm downloads from 2026-08-19 through 2026-08-25, and the monorepo has 76,460 stars. Official packages connect the same container to Express, Fastify, GraphQL, WebSockets, message transports, configuration, and testing. The package bundles TypeScript declarations, and our Node 22 check loaded its CommonJS build through both `require()` and ESM import, which covers the usual server module setups.

Use it if

  • Several teams need one enforced structure for modules, providers, controllers, and the request lifecycle.
  • The backend will combine official Nest integrations for GraphQL, WebSockets, jobs, scheduling, or message transports.
  • The codebase already accepts decorators, constructor injection, and class-centered TypeScript design.
  • Tests benefit from replacing a provider in a compiled module rather than monkeypatching imports.
Skip it if

Setup reality

We installed @nestjs/core 11.2.1 in a fresh Node 22 Bookworm container in 8.8 seconds. The result was 27 packages using 17 MB, with zero findings from npm audit. Core itself declared 5 direct and 6 peer dependencies and was 1,916 KB unpacked. Bundled types were present. Both require() and ESM import worked even though the package is CommonJS and has no exports map. The browser build failed in esbuild, which is the expected result for this Node-only runtime.

Three peers are basic requirements: @nestjs/common, rxjs, and reflect-metadata. The peer list also includes platform-express, websockets, and microservices as optional. An HTTP service must install either @nestjs/platform-express or @nestjs/platform-fastify on the same Nest major. A manual TypeScript setup also needs decorator metadata enabled and loaded before decorated application classes. NestFactory.create() cannot start until a root module has been defined.

Core does not include request validation. DTO validation usually adds class-validator, class-transformer, and a ValidationPipe; configuration, OpenAPI, GraphQL, queues, and persistence are separate choices too. Module boundaries control provider visibility, so a provider must be exported by its declaring module and that module imported by its consumer. Register injected global guards, pipes, filters, and interceptors with the APP_* tokens. Instances passed directly with new sit outside ordinary container construction.

Express and Fastify adapters expose different middleware and request objects. A Fastify server in a container normally listens on 0.0.0.0, not only loopback. Enable shutdown hooks if providers must release resources on SIGTERM. The 11.2 series changed lazy-module and SSE behavior, then 11.2.2 and 11.2.3 repaired startup and circular durable-provider failures. We measured 11.2.1, so teams using those features should take the current 11.2.3 patch and rerun their bootstrap tests.

Patterns

Start an HTTP application bootstrap-application

import 'reflect-metadata';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function start() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix('api');
  await app.listen(Number(process.env.PORT ?? 3000));
}
void start();

A manual project must import `reflect-metadata` before its decorated classes load. CLI-generated projects already include the matching compiler configuration.

Expose a provider from a feature module declare-module

import { Module } from '@nestjs/common';
import { OrdersController } from './orders.controller';
import { OrdersService } from './orders.service';

@Module({
  controllers: [OrdersController],
  providers: [OrdersService],
  exports: [OrdersService],
})
export class OrdersModule {}

`OrdersService` stays inside this module until `exports` exposes it. Another module must import `OrdersModule` before injection can resolve the service.

Map requests to controller methods create-controller

import { Body, Controller, Get, Param, Post } from '@nestjs/common';

@Controller('orders')
export class OrdersController {
  constructor(private readonly orders: OrdersService) {}

  @Get(':id')
  find(@Param('id') id: string) {
    return this.orders.find(id);
  }

  @Post()
  create(@Body() input: CreateOrderDto) {
    return this.orders.create(input);
  }
}

A returned value passes through Nest serialization and interceptors. Writing through the adapter response object can switch the handler to platform-specific response handling.

Create a service for constructor injection inject-provider

import { Injectable, NotFoundException } from '@nestjs/common';

@Injectable()
export class OrdersService {
  constructor(private readonly store: OrderStore) {}

  async find(id: string) {
    const order = await this.store.find(id);
    if (!order) throw new NotFoundException(`Order ${id} was not found`);
    return order;
  }
}

The module graph must make both provider tokens visible. `NotFoundException` carries HTTP 404, whereas an ordinary `Error` becomes an internal-server response.

Strip unknown fields and validate DTOs validate-request-body

import { ValidationPipe } from '@nestjs/common';
import { IsInt, IsString, Min } from 'class-validator';

export class CreateOrderDto {
  @IsString() customerId!: string;
  @IsInt() @Min(1) quantity!: number;
}

app.useGlobalPipes(new ValidationPipe({
  whitelist: true,
  transform: true,
}));

Core does not install `class-validator` or `class-transformer`. `whitelist` strips unknown fields; `forbidNonWhitelisted` turns them into a request error.

Reject requests through a guard protect-routes

import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';

@Injectable()
export class ApiKeyGuard implements CanActivate {
  canActivate(context: ExecutionContext) {
    const request = context.switchToHttp().getRequest();
    if (request.headers['x-api-key'] !== process.env.API_KEY) {
      throw new UnauthorizedException();
    }
    return true;
  }
}

A guard that returns `false` yields HTTP 403. Throw `UnauthorizedException` when failed authentication must produce HTTP 401 instead.

Register a global guard with dependency injection register-global-guard

import { APP_GUARD } from '@nestjs/core';

@Module({
  providers: [
    ApiKeyGuard,
    { provide: APP_GUARD, useExisting: ApiKeyGuard },
  ],
})
export class SecurityModule {}

An instance passed to `useGlobalGuards()` was constructed outside the container. `APP_GUARD` lets Nest resolve its constructor dependencies normally.

Run Nest on the Fastify adapter switch-to-fastify

import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';

const app = await NestFactory.create<NestFastifyApplication>(
  AppModule,
  new FastifyAdapter(),
);
await app.listen({ port: 3000, host: '0.0.0.0' });

Keep `@nestjs/platform-fastify` on core's major version. Middleware using Express-only request or response methods cannot move across unchanged.

Replace a provider in a unit test test-with-container

const moduleRef = await Test.createTestingModule({
  controllers: [OrdersController],
  providers: [OrdersService, OrderStore],
})
  .overrideProvider(OrderStore)
  .useValue({ find: jest.fn().mockResolvedValue({ id: 'o1' }) })
  .compile();

const controller = moduleRef.get(OrdersController);
await expect(controller.find('o1')).resolves.toEqual({ id: 'o1' });

`Test` comes from the separate `@nestjs/testing` package. A small testing module avoids booting the HTTP adapter and unrelated providers.

Close resources when the process receives SIGTERM handle-shutdown

@Injectable()
export class DatabaseService implements OnApplicationShutdown {
  constructor(private readonly pool: Pool) {}

  async onApplicationShutdown() {
    await this.pool.end();
  }
}

app.enableShutdownHooks();

`enableShutdownHooks()` connects process signals to lifecycle methods. Several Nest applications in one process each add listeners and can trigger listener-limit warnings.

Configure a reusable module asynchronously create-dynamic-module

@Module({})
export class StorageModule {
  static forRootAsync(): DynamicModule {
    return {
      module: StorageModule,
      providers: [{
        provide: 'STORAGE_OPTIONS',
        inject: [ConfigService],
        useFactory: (config: ConfigService) => ({ bucket: config.getOrThrow('BUCKET') }),
      }],
      exports: ['STORAGE_OPTIONS'],
    };
  }
}

Dynamic configuration does not bypass module visibility. Export the token and import the returned module wherever consumers need it.

Return a server-sent event stream send-server-events

import { Controller, MessageEvent, Sse } from '@nestjs/common';
import { interval, map, Observable } from 'rxjs';

@Controller('jobs')
export class JobsController {
  @Sse('events')
  events(): Observable<MessageEvent> {
    return interval(1000).pipe(
      map((count) => ({ data: { count } })),
    );
  }
}

The observable emits `MessageEvent` shapes. The 11.2 line changed disconnect cancellation, and 11.2.1 repaired an early-return path; current 11.2.3 includes that fix.

Alternatives

PackageRegistryPick it when
fastifynpmPick it for schema-aware HTTP handling when the team wants to choose its own architecture.
expressnpmPick it for a small or middleware-heavy service that does not need a dependency-injection container.
hononpmPick it when the same compact routing API must run on edge platforms as well as Node.

More web backend guides

urllib3 · requests · ws · anyio · undici · httpx · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.