I’m excited to officially announce the release of NestJS 11! This update is packed with numerous bug fixes, enhancements, and brand-new features. While there are too many to cover in full, let’s explore some of the most noteworthy highlights!
In case you're not familiar with NestJS, it is a TypeScript Node.js framework that helps you build enterprise-grade efficient and scalable Node.js applications.
Photo by Vadim Bogulov. Sumy, Ukraine
Let's dive right in! 🐈
Logger enhancements
The default logger in NestJS, ConsoleLogger
, has received a major upgrade in this release. It now includes several improvements such as better formatting for deeply nested objects and arrays, support for maps and sets, and the ability to customize log prefixes. However, the standout feature is the new built-in support for JSON logging.
You can now enable JSON-formatted logs with a simple configuration:
const app = await NestFactory.create(AppModule, { logger: new ConsoleLogger({ json: true, }),});
Setting the json
option to true
ensures logs are output in JSON format, making them ideal for containerized environments. This enables seamless parsing and analysis of logs without needing third-party tools or libraries for JSON formatting. Simply enable the json
option, and you're all set!
When JSON logging is enabled, colors are turned off by default. However, you can re-enable them for easier readability during local development by setting the colors
option to true
:
const app = await NestFactory.create(AppModule, { logger: new ConsoleLogger({ json: true, colors: true, }),});
This flexibility ensures that your logs remain both functional and visually accessible, whether you're developing locally or deploying to production.
Check out this PR to learn more about the changes to the logger.
More flexible microservices
With the release of NestJS 11, significant improvements have been made to all officially supported microservice transporters, such as NATS, Kafka, Redis, and others. These upgrades are designed to provide developers with greater flexibility, reliability, and control over how they interact with brokers and services. Whether you are building a simple service or a highly complex distributed architecture, these new features are sure to enhance your development experience.
The new unwrap
method allows direct access to the underlying client instance, enabling custom operations that go beyond the standard NestJS API. For example, you can access the raw client instance and leverage its native methods or inspect its internal state:
import { NatsConnection } from 'nats';// In the bootstrap functionconst serviceRef = app.connectMicroservice({ transport: Transport.NATS, options: { // NATS connection options here },});const connection = serviceRef.unwrap<NatsConnection>();console.log(connection.info);
NATS is used as an example here, but the
unwrap
method is available for all the other transporters as well.
This method gives you full access to the native client and its features, enabling advanced use cases like inspecting connection details, performing low-level configurations, or extending functionality.
In addition to unwrapping the client instance, you can now listen to internal events emitted by the underlying client using the new on
method. This is particularly useful for monitoring critical events, such as disconnections or errors:
const serviceRef = app.connectMicroservice({ transport: Transport.NATS, options: { // NATS connection options here },});serviceRef.on<NatsEvents>('disconnect', () => { console.log('Client disconnected');});
This feature makes it easier to react to network issues or other disruptions in real-time, ensuring that your application remains resilient and responsive.
Another powerful addition is the status
observable stream, which provides real-time updates on the client instance's current state. By subscribing to this stream, you can monitor connection status dynamically:
const serviceRef = app.connectMicroservice({ transport: Transport.NATS, options: { // NATS connection options here },});serviceRef.status.subscribe((status) => { console.log('Status:', status);});
The status observable emits events like connecting
, connected
, disconnected
, and reconnecting
(depending on the transporter), giving you deeper visibility into the health of your microservices and allowing for proactive troubleshooting.
The ClientProxy
class also provides the same API set of methods, ensuring a unified and consistent experience when monitoring and interacting with underlying client instances. Whether you're using it to handle events or observe the status of a client, the process remains straightforward and intuitive.
// Injecting the client instanceconstructor( @Inject(MATH_SERVICE) private readonly client: ClientProxy<NatsEvents>,) {}// Listening to events and statusthis.client.on('disconnect', () => console.log('Disconnected'));this.client.status.subscribe(status => { console.log('Status:', status);});
These new capabilities give you greater control and insight into your microservices, simplifying the development of complex distributed systems. For further examples and detailed information, check out the official documentation.
Faster application startup
In NestJS 11, we've overhauled the module opaque key generation process to improve application startup times.
In previous versions, the framework used a hash function to generate opaque keys for dynamic modules by serializing their metadata to create unique identifiers. While this enabled certain internal optimizations, it also added unnecessary complexity and performance overhead, especially for dynamic modules with large inputs (e.g., JSON files), where hash generation was slow and inefficient.
Starting with v11, the framework has adopted a more straightforward approach. Instead of hashing the entire module metadata, it now uses object references to generate opaque keys. This change is largely transparent to most users but significantly boosts startup performance for applications with large dynamic modules.
The only case in which you might notice a difference in framework behavior is when your application imports the same dynamic module multiple times (with a deeply equal configuration). In this scenario, the framework will now treat these modules as separate instances, whereas previously, they would have been merged into a single instance. For those who rely on this behavior, you can assign your dynamic module to a variable and import it multiple times to ensure the same instance is used across your application
const myModule = DynamicModule.forRoot({})
.
Express v5 and Fastify v5
NestJS 11 now supports the latest versions of Express and Fastify, ensuring you have the most up-to-date dependencies. While upgrading to Fastify v5 should be smooth for most users, the update to Express v5 may require some adjustments due to breaking changes in the underlying library.
One of the most notable updates in Express v5 is the revised path route matching algorithm. The following changes have been introduced to how path strings are matched with incoming requests:
- The wildcard
*
must have a name, matching the behavior of parameters :, use/*splat
or/{*splat}
instead of/*
.splat
is simply the name of the wildcard parameter and has no special meaning. You can name it anything you like, for example,*wildcard
. - The optional character
?
is no longer supported, use braces instead:/:file{.:ext}
. - Regexp characters are not supported.
- Some characters have been reserved to avoid confusion during upgrade
(()[]?+!)
, use\
to escape them. - Parameter names now support valid JavaScript identifiers, or quoted like
:"this"
.
That said, routes that previously worked in Express v4 may not work in Express v5. For example:
@Get('users/*')findAll() { // In NestJS 11, this will be automatically converted to a valid Express v5 route. // While it may still work, it's no longer advisable to use this wildcard syntax in Express v5. return 'This route should not work in Express v5';}
To fix this issue, you can update the route to use a named wildcard:
@Get('users/*splat')findAll() { return 'This route will work in Express v5';}
Note that
*splat
is a named wildcard that matches any path without the root path. If you need to match the root path as well (/users
), you can use/users/{*splat}
, wrapping the wildcard in braces (optional group). Note thatsplat
is simply the name of the wildcard parameter and has no special meaning. You can name it anything you like, for example,*wildcard
.
Check out the migration guide to learn more about the changes in Express v5 and how to update your routes accordingly.
Some other valuable updates
- The order of termination lifecycle hooks (
OnModuleDestroy
,OnApplicationShutdown
, etc.) has been reversed. Read more here. CacheModule
has been updated to use the latest version ofcache-manager
(v6), which now utilizesKeyv
for a unified interface for key-value storage. See the migration guide.- A new
ParseDatePipe
has been added to@nestjs/common
, making it easier to work with dates. - Microservice options can now be provided from the DI container, thanks to jmcdo29. See this PR.
IntrinsicException
has been introduced in@nestjs/common
, allowing you to throw exceptions that won’t be auto-logged by the framework. See this PR.@nestjs/cqrs
now supports request-scoped providers and strongly-typed commands, events, and queries. Check the official documentation for more details.Reflector#getAll
andReflector#getAllAndMerge
will now correctly infer transformed metadata types.ConfigService#get
now reads configuration values in a different order, allowing users to overrideprocess.env
values from custom config factories. Additionally, theskipProcessEnv
option has been introduced, simplifying the encapsulation of configuration values (especially useful for testing). See here.- And many more! Check out the full release notes here
Migration from Nest v10
To migrate your existing project to NestJS 11, refer to the detailed guidelines provided here. These steps will help ensure a smooth transition by addressing all the necessary changes and updates.
Enjoy v11!
We're excited to see how you use the latest version of NestJS.
Make sure to follow Nest on X @nestframework to stay up to date with all the latest announcements!
Enterprise Consulting & Support
Our official NestJS Enterprise Consulting includes a broad range of services to empower your team.
We work alongside you to meet your deadlines while avoiding costly tech debt. Challenging issue? We've got you covered.
- Providing technical guidance & architectural reviews
- Mentoring team members
- Addressing security & performance concerns
- Performing in-depth code reviews
- Long-term support (LTS) & upgrade assistance
Our goal is to help you get to market faster. Nest core team members will help you utilize best practices and choose the right strategy for unique goals. You can learn more on the enterprise.nestjs.com.
Support the NestJS Project
Nest is an MIT-licensed open source project with its ongoing development made possible thanks to the support by the community and our sponsors. Thank you!
This framework is a result of the long days, sleepless nights, and busy weekends. And we fully rely on the goodness ❤️ of the people. If you want to join them, you can read more here.
Thank you
To all backers, sponsors, contributors, and community, thank you once again! This product is for you. And this is only the beginning of the long 🚀 story.
Become a Backer or Sponsor to Nest by donating to our open collective. ❤
Learn NestJS - Official NestJS Courses 📚
Level-up your NestJS and Node.js ecosystem skills in these incremental workshop-style courses, from the NestJS Creator himself, and help support the NestJS framework! 🐈🚀 The NestJS Fundamentals Course is now LIVE and 25% off for a limited time!
🎉 NEW - NestJS Course Extensions now live!
- NestJS Advanced Concepts Course now LIVE!
- NestJS Advanced Bundle (Advanced Architecture and Advanced Concepts) now 22% OFF!
- NestJS Microservices now LIVE!
- NestJS Authentication / Authorization Course now LIVE!
- NestJS GraphQL Course (code-first & schema-first approaches) are now LIVE!
- NestJS Authentication / Authorization Course now LIVE!