Warning: This package is in the early development stage. It is not recommended to use it in production before the first major version.
- Motivation
- Installation steps
- Configuration
- Logging
- Http server
- Production-ready features
- Package update flow
NestJs is great, but compared to mature frameworks from other ecosystems, like Spring Boot, Laravel, Ruby on Rails, it is still considered a micro-framework. The building blocks of the application are very small, and this approach does not scale well. Often, a higher level of abstraction is required. Also, the NestJS community overlooks production-ready practices, focusing on "hello world" solutions. A glaring example is the complete disregard for observability tools. Here, there are no official solutions, no mature community-driven solutions.
This starter provides the core block, including tools that are used in most projects:
- Configuration
- Logging
- HTTP server
- Swagger doc
- Graceful shutdown
- Healthcheck
- Metrics (prometheus)
Essential subjects:
- Each module should answer the question "Why include it in the starter?"
- Each module should be configurable with the internal configuration module.
- The starter should be easily extendable and not hinder application customization.
- Prohibition on inventing wheels.
Prerequisites:
- NestJs project with nest version 10+
npm i @monkee/nestjs-starter @monkee/turbo-config@2 @nestjs/swagger@7 class-validator@0.13.2
import { NestStarterConfig } from '@monkee/nestjs-starter';
// Starter config contains all necessary configuration for included modules
export class AppConfig extends NestStarterConfig {}
import { Module } from '@nestjs/common';
import { createStarterModules } from '@monkee/nestjs-starter';
import { AppConfig } from './app.config';
@Module({
imports: [
...createStarterModules(AppConfig),
// other modules
],
})
export class AppModule {}
import { createStarterApp, initStarterApp, startStarterApp } from '@monkee/nestjs-starter';
import { AppConfig } from './app.config';
import { AppModule } from './app.module';
const main = async () => {
const app = await createStarterApp(AppModule);
await initStarterApp(app, AppConfig);
// on this step you can add your own initialization logic
// for example, you can add custom global pipes, guards, interceptors, etc.
await startStarterApp(app, AppConfig);
};
main();
It's hard to imagine an application that doesn't require configuration. Also, starter already includes several components that need to be configured.
The built-in solution simply lacks behind competitors in the market. Features that are found in one form or another in other frameworks (Spring Boot, ASP Net) are missing in @nestjs/config.
- Multiple configuration sources (yml, envs, cli)
- Support for parsing into a typed data structure
- Using the same validation solution as the rest of the application
- Support for data structures (arrays, maps)
- Developer UX tools (autocomplete for yml configs)
- Config documentation generator
This starter provides a high-level tool for configuring your applications. Many configuration rules are strictly enforced, and this is done intentionally.
Key points:
- The application is configured using YML files with the ability to override settings through YML, environment variables, or CLI arguments.
- There is always a default configuration file named config.default.yml.
- Separate YML files can be created for each environment. The environment name is set by the NEST_CONFIG_ENV environment variable. Examples: config.production.yml, config.test.yml
- The root directory by default is "src/resources". The root directory can be reassigned via the NEST_CONFIG_ROOT environment variable. You should properly configure the production container build
- If the application is started with NEST_CONFIG_GENERATE_REF=true, config reference and json schema is automatically generated
The starter uses the @monkee/turbo-config library under the hood. Refer to the documentation for more details.
Application without logging is like a car without a dashboard. You can drive it, but you don't know what's going on under the hood (Copilot generated this analogy).
Starter provides a pre-configured logging module that implements the standard NestJs Logger interface.
Since there is currently no established format for structured logs (waiting for https://www.cncf.io/projects/opentelemetry/ graduated state), the format was chosen based on popular solutions: zerolog from the Golang ecosystem, and Logback from Java.
Log format with basic fields:
{
"timestamp": 1696689301574,
"level": "debug",
"message": "Debug message",
"context": "default",
"traceId": "25215d96-e247-40b4-8146-a93f1b9250c0"
}
# HELP nest_log_events_total Total count of log events
# TYPE nest_log_events_total counter
nest_log_events_total{level="debug",context="default"} 1
It would be entirely correct to say that not every application requires an HTTP server. However, it is an integral part of NestJS itself, and we have decided to make it part of the starter as well.
NestJS suffers from a lack of abstraction over the HTTP server, directly referencing implementations: Express or Fastify. Otherwise, the solution works well.
The starter provides a pre-configured setup of Fastify. It was chosen as a more maintained project. Also, for some projects, performance may be a critical factor.
# HELP http_server_requests_seconds Http server request time seconds
# TYPE http_server_requests_seconds histogram
nest_http_requests_seconds_bucket{le="+Inf",method="GET",uri="/hello",status="200"} 1
nest_http_requests_seconds_sum{method="GET",uri="/hello",status="200"} 0.0008857910000006086
nest_http_requests_seconds_count{method="GET",uri="/hello",status="200"} 1
Yes, our team couldn't come up with our own term. The actuator is a well-known concept from the Spring Boot ecosystem. The actuator mainly exposes operational information about the running application — health, metrics, info etc.
Essential feature for cloud deployments. "Zero-downtime" deployment is a must-have for any modern application.
The starter provides two simple health checks:
- /actuator/health - At the moment, it will only detect application freeze, without checking system components. Can be used as a liveness probe with caution.
- /actuator/readiness - This endpoint checks the http server readiness. It can be used as a readiness probe.
Surprisingly, the observability point is simply absent from the NestJS documentation. Any modern application should have monitoring tools.
The starter provides a module for Prometheus. The module implements the standard interface, so all starter modules and third-party modules that implement the interface can provide their own metrics.
The starter already includes metrics for:
- HTTP module
- Logging module
- Default Node.js process
Default metrics endpoint is
/actuator/prometheus
Package publishing only available via CI jobs.
You must use '-beta' postfix for testing purposes. Otherwise CI job being failed. Bump version via npm
npm version prerelease --preid beta
Before merge changes into master branch you should remove 'beta' postfix
npm version major | minor | patch
Learn more https://docs.npmjs.com/cli/v8/commands/npm-version