nest
v12.5.0A progressive TypeScript framework for Node.js backends: from a small API in one file to efficient, scalable, enterprise-grade systems 🚀
- Maintenance
- Active992 commits in 3 months · bus factor 1
- License
- MITPermissive · OSI-approved
- Security
- 19 advisories1 critical, 16 high, 2 medium · Scorecard 7.5/10
- Supported versions
- 2 lines supportednewest 12 · oldest 11 · 4 ended
77.1k stars · 8.7k forks · 46 open issues · last release 3 days ago · data checked 4 hours ago
Supported versions
Source: endoflife.date| Line | Latest | Released | Security fixes |
|---|---|---|---|
| 12 | 12.5.0 | Aug 27, 2026 | Supported |
| 11 | 11.2.10 | Jan 20, 2025 | Supported |
| 10 | 10.4.22 | Jun 15, 2023 | Ended |
| 9 | 9.4.3 | Jul 8, 2022 | Ended |
| 8 | 8.4.7 | Jul 7, 2021 | Ended |
| 7 | 7.6.18 | Mar 13, 2020 | Ended |
Breaking changes
What to check before upgrading, taken from the notes of the last 30 releases.
- v12.0.0Aug 27, 2026
Upgrading
Upgrade the CLI first, since the upgrade command ships with it:
npm i -g @nestjs/cli@latestThen, from the root of your project:
nest upgradenest upgrademoves every@nestjs/*package to its v12-compatible major at once and applies the mechanical parts of the migration for you —nest-cli.jsonwebpack options, the GraphQLplayground→graphiqlrename and subscriptions transport swap, the NATS package replacement,@nestjs/configvalidation options, Jest and Joi bumps — then prints a report of everything it changed and everything you still need to review by hand. Run it with--dry-runfirst to see that report without touching your files.It deliberately does not migrate your project to ESM, Vitest, or oxlint. Those are the defaults for newly generated projects; existing projects adopt them on their own schedule.
Node.js: v12 requires Node.js v20.19+ or v22.12+. Both
require(esm)and the ESM packages depend on it; the upgrade command refuses to run on older releases (including the 21.x line). The latest active LTS is recommended.---
Breaking changes
| Change | What to do |
| --- | --- |
| Packages ship as ESM | Usually nothing —
require(esm)keeps CommonJS apps working. Review custom bootstrapping, bundler, and test-runner config. || Node.js v20.19+ / v22.12+ required | Upgrade Node; the 21.x line is not supported. |
| Lifecycle hooks are now invoked by component hierarchy level | Review ordering assumptions between related providers/modules in init, teardown, and tests. |
| NATS v3 — the
natspackage is replaced by@nats-io/transport-node|npm uninstall nats && npm install @nats-io/transport-node; update direct imports. Packets are now serialized as JSON strings and custom deserializers receive the full NATS message — read payloads withmsg.json(). || GraphQL subscriptions —
subscriptions-transport-wssupport removed | Switch tographql-ws; the protocols are wire-incompatible, so clients must be updated. ReviewonConnectcallbacks. || GraphiQL is the default GraphQL IDE | Replace
playgroundwithgraphiql; pass an options object to customize. ||
@nestjs/configvalidates through Standard Schema | Keep Joi by upgrading to v18+ and moving library settings undervalidationOptions.libraryOptions. || Pipe transform signatures refined;
ArgumentMetadatais now generic | Adjust hand-written custom pipe signatures if the compiler complains. ||
ConsoleLoggerstructured params on by default | SetstructuredParams: falseto restore the previous output. || Webpack CLI workflows deprecated | Migrate to
--builder rspack. ||
angularschematic removed | — |Most of these are handled automatically by
nest upgrade.
Release history
All releases on GitHubWhat's changed
@nestjs/common- fix(common): let a null depth print every level in the console logger — backport of #18480
- fix(common): count empty strings toward the json log record cap
- fix(common): check the json log record cap before converting values
- fix(common): limit the error messages of parsed array items in total
- fix(common): rethrow non-validation errors in the parse array pipe
- fix(common): drop the value of validation errors that have children
- fix(common): reject a buffer sent in place of a validated class
- fix(common): reject a buffer held by a nested validated property
- fix(common): validate a stand-in for a buffer sent as the whole value
- fix(common,core): use the default for pipe and sse limits given as nan
- fix(common): validate the files of parse file pipe one at a time
- fix(common): close the gaps of sparse arrays the pipes validate
- fix(common,core): count sse events without data toward the pending limit
- fix(common,core): send the status text in sse errors that wrap an error
- fix(common): keep the scope a class declares when passed to mixin()
@nestjs/core- fix(core): listen for the error of every stream the router holds
- fix(core): share one close listener among the requests of a connection
- fix(core): send what the interceptors return for a streaming handler
- fix(core): catch what the teardown of an sse producer throws
- fix(core): write the waiting events of an sse client in linear time
- fix(core): notice an sse client that left while its socket is paused
- fix(core): keep host params matched next to an optional group
- fix(core): answer http errors that graphql or async rpc filters leave
- fix(core): skip exception filters that were not created for a request
- fix(core): keep a controller root route next to an optional-tail route
- fix(core,fastify): exclude "/x/" only when no other route may serve it
- fix(core,fastify,node): match excluded params up to the router's limit
- fix(core,fastify): end the excluded path at ";" like the fastify router
- fix(core,fastify): match the text after an excluded param as written
- fix(core): run the middleware for a path with a line terminator
- fix(core): mount middleware where the router serves the covered routes
- fix(core): test each versioned path against the prefix exclusions alone
- fix(core): keep the filters of a middleware's use() with exclude()
- fix(core): warn that filter classes bound to a middleware do not apply
- fix(core): reject a middleware target that is not a controller or route — such an entry now fails the application at startup
- fix(core): mount module middleware in order when configure() awaits
- fix(core): resolve a forward reference to a module only once
- fix(core): mount a controller root route without the slash after a tail
- fix(core): mount middleware on a route path that really ends in "$"
- fix(core): keep create() working after many calls in snapshot mode
- fix(core): give unserializable dynamic modules their own deep-hash ids
- fix(core): build a lazy module once when loads overlap
- fix(core): fail the consumer when an optional dependency fails to load
- fix(core): keep transient instances out of durable sub-trees
- fix(core): inject the strategy payload into durable providers as request
- fix(core): inject the provider an alias stands for
- fix(core,websockets): read parameter metadata from the declaring class
- fix(core,common): read the catch types of a filter from its prototype
- fix(core): warn when a validation pipe gets no parameter types
- fix(core): use the enhancers of the module that holds the host
- fix(core): run the container instance of a class-bound enhancer
- fix(core): throw for a guard, interceptor or pipe that can't run — such a binding now fails the application at startup
- fix(core,microservices,websockets): drop gateway clients during startup
- fix(core): warn about an exception filter that can't run
- fix(core): settle sse lifecycle on early disconnect — backport of #17987
- fix(core): let exclusions cover routes excluded from the global prefix — backport of #18209
- fix(core): compare a prefix exclusion with a trailing slash as served