How to manage configuration in NestJS with configmodule?
Configuration Management in NestJS
NestJS provides @nestjs/config — a module that loads environment variables from .env files and exposes them via a type-safe ConfigService.
Setup
bash
npm install @nestjs/configtypescript
// app.module.ts
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true, // no need to import in every module
envFilePath: '.env',
cache: true, // cache values for performance
}),
],
})
export class AppModule {}Using ConfigService
typescript
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class DatabaseService {
constructor(private configService: ConfigService) {}
getConnectionString(): string {
const host = this.configService.get<string>('DB_HOST');
const port = this.configService.get<number>('DB_PORT', 5432); // default 5432
const name = this.configService.get<string>('DB_NAME');
return `postgres://${host}:${port}/${name}`;
}
}Typed Configuration (Namespaced)
typescript
// config/database.config.ts
import { registerAs } from '@nestjs/config';
export default registerAs('database', () => ({
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432', 10),
name: process.env.DB_NAME || 'mydb',
password: process.env.DB_PASS,
}));
// app.module.ts
import databaseConfig from './config/database.config';
ConfigModule.forRoot({
isGlobal: true,
load: [databaseConfig],
})
// Usage:
const dbHost = this.configService.get<string>('database.host');
const dbPort = this.configService.get<number>('database.port');Environment Validation with Joi
bash
npm install joitypescript
import * as Joi from 'joi';
ConfigModule.forRoot({
isGlobal: true,
validationSchema: Joi.object({
NODE_ENV: Joi.string().valid('development', 'production', 'test').required(),
PORT: Joi.number().default(3000),
DB_HOST: Joi.string().required(),
DB_PORT: Joi.number().default(5432),
DB_USER: Joi.string().required(),
DB_PASS: Joi.string().required(),
DB_NAME: Joi.string().required(),
JWT_SECRET: Joi.string().min(32).required(),
}),
validationOptions: {
allowUnknown: true,
abortEarly: false, // show all errors at once
},
})If validation fails, the app refuses to start — catching missing env vars early.
Using Config in forRoot() (e.g., TypeORM)
typescript
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (config: ConfigService) => ({
type: 'postgres',
host: config.get('DB_HOST'),
port: config.get<number>('DB_PORT'),
username: config.get('DB_USER'),
password: config.get('DB_PASS'),
database: config.get('DB_NAME'),
autoLoadEntities: true,
synchronize: config.get('NODE_ENV') !== 'production',
}),
inject: [ConfigService],
})Multiple .env Files
typescript
ConfigModule.forRoot({
envFilePath: [
`.env.${process.env.NODE_ENV}.local`,
`.env.${process.env.NODE_ENV}`,
'.env.local',
'.env',
],
})Summary
Use ConfigModule.forRoot({ isGlobal: true }) to load .env once and make ConfigService available everywhere. Add validationSchema with Joi to validate required variables at startup. Use registerAs() for typed, namespaced config objects.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.