nself provides comprehensive support for NestJS microservices, enabling you to build scalable, modular backend services that integrate seamlessly with your nself stack. With built-in templates, automatic configuration, and production-ready deployment, you can focus on building features while nself handles the infrastructure.
NestJS is a progressive Node.js framework for building efficient and scalable server-side applications. When combined with nself, you get:
Add NestJS services to your .env.local
:
# Enable NestJS microservices
NESTJS_SERVICES=api,webhooks,auth-service
# Optional: Specify NestJS version
NESTJS_VERSION=10.x
# Optional: Enable additional features
NESTJS_SWAGGER=true
NESTJS_VALIDATION=true
NESTJS_CACHE=true
# Generate NestJS services
nself build
# Start services
nself up
This creates the following structure:
services/
├── nestjs/
│ ├── api/ # Main API service
│ │ ├── src/
│ │ ├── Dockerfile
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── webhooks/ # Webhook handler service
│ └── auth-service/ # Authentication microservice
└── shared/
└── types/ # Shared TypeScript types
Basic REST API with database integration:
// src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from '@nestjs/config';
import { UsersModule } from './users/users.module';
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRoot({
type: 'postgres',
host: process.env.POSTGRES_HOST,
port: parseInt(process.env.POSTGRES_PORT),
username: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DB,
autoLoadEntities: true,
synchronize: false, // Use nself migrations instead
}),
UsersModule,
],
})
export class AppModule {}
Integration with Hasura GraphQL:
// src/graphql/graphql.module.ts
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriverConfig, ApolloDriver } from '@nestjs/apollo';
@Module({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: 'schema.gql',
context: ({ req }) => ({ req }),
introspection: true,
playground: true,
}),
],
})
export class GraphQLAppModule {}
BullMQ integration for background jobs:
// src/jobs/jobs.module.ts
import { Module } from '@nestjs/common';
import { BullModule } from '@nestjs/bull';
import { EmailProcessor } from './processors/email.processor';
@Module({
imports: [
BullModule.forRoot({
redis: {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT),
},
}),
BullModule.registerQueue({
name: 'email',
}),
],
providers: [EmailProcessor],
})
export class JobsModule {}
Pre-configured TypeORM setup with nself database:
// src/database/database.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigService } from '@nestjs/config';
@Module({
imports: [
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
type: 'postgres',
host: config.get('POSTGRES_HOST'),
port: config.get('POSTGRES_PORT'),
username: config.get('POSTGRES_USER'),
password: config.get('POSTGRES_PASSWORD'),
database: config.get('POSTGRES_DB'),
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
synchronize: false,
logging: config.get('NODE_ENV') === 'development',
ssl: config.get('NODE_ENV') === 'production' ? { rejectUnauthorized: false } : false,
}),
}),
],
})
export class DatabaseModule {}
// src/users/entities/user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
@Entity('users')
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ unique: true })
email: string;
@Column()
password_hash: string;
@Column({ nullable: true })
first_name: string;
@Column({ nullable: true })
last_name: string;
@Column({ default: true })
is_active: boolean;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
}
JWT authentication with nself's auth service:
// src/auth/auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const token = request.headers.authorization?.split(' ')[1];
if (!token) return false;
try {
const payload = this.jwtService.verify(token);
request.user = payload;
return true;
} catch {
return false;
}
}
}
Automatic health check endpoints:
// src/health/health.controller.ts
import { Controller, Get } from '@nestjs/common';
import { HealthCheckService, HealthCheck, TypeOrmHealthIndicator } from '@nestjs/terminus';
@Controller('health')
export class HealthController {
constructor(
private health: HealthCheckService,
private db: TypeOrmHealthIndicator,
) {}
@Get()
@HealthCheck()
check() {
return this.health.check([
() => this.db.pingCheck('database'),
]);
}
}
// src/common/interceptors/logging.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, Logger } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
private readonly logger = new Logger(LoggingInterceptor.name);
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const method = request.method;
const url = request.url;
const now = Date.now();
return next.handle().pipe(
tap(() => {
const response = context.switchToHttp().getResponse();
const statusCode = response.statusCode;
const delay = Date.now() - now;
this.logger.log(`${method} ${url} ${statusCode} - ${delay}ms`);
}),
);
}
}
Each NestJS service gets optimized Docker configuration:
# Dockerfile (auto-generated)
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
FROM node:18-alpine AS runtime
WORKDIR /app
# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nestjs -u 1001
# Copy built application
COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules
COPY --chown=nestjs:nodejs . .
USER nestjs
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
CMD ["npm", "run", "start:prod"]
# Scale specific services
NESTJS_API_REPLICAS=3
NESTJS_WEBHOOKS_REPLICAS=2
NESTJS_AUTH_REPLICAS=2
# Configure in .env.local and rebuild
nself build && nself restart
# Generate new NestJS service
nself generate nestjs --name user-service
# Add new module to existing service
nself generate nestjs:module --service api --name payments
# Add controller
nself generate nestjs:controller --service api --name users
# Add service provider
nself generate nestjs:service --service api --name users
# Watch mode for development
nself dev nestjs --service api
# Run tests
nself test nestjs --service api
# View service logs
nself logs nestjs --service api --follow
# Execute commands in service
nself exec nestjs api npm run migration:generate
Now that you understand NestJS microservices:
NestJS services provide a robust, scalable foundation for building enterprise-grade applications with nself.