The @nestjs/config helps manage environment variables (.env) in a clean and scalable way.
👉 Why use it?
Example:
import { ConfigModule } from '@nestjs/config';@Module({imports: [ConfigModule.forRoot()],})export class AppModule {}
Now you can use .env:
PORT=3000DB_HOST=localhost
You can load different .env files depending on environment.
👉 Useful for:
.env.development.env.productionExample:
ConfigModule.forRoot({envFilePath: '.env.development',});
Or multiple:
ConfigModule.forRoot({envFilePath: ['.env.development', '.env'],});
Use Joi to validate environment variables at startup.
👉 Prevents runtime errors due to missing/invalid config.
Example:
import * as Joi from 'joi';ConfigModule.forRoot({validationSchema: Joi.object({PORT: Joi.number().required(),DB_HOST: Joi.string().required(),}),});
Use ConfigService to access config values anywhere.
Example:
import { ConfigService } from '@nestjs/config';@Injectable()export class AppService {constructor(private configService: ConfigService) {}getPort() {return this.configService.get<number>('PORT');}}
👉 Pro tip: Add default values
this.configService.get<number>('PORT', 3000);
Instead of using only .env, you can define structured config files.
👉 Good for grouping related config (DB, auth, etc.)
Example:
// config/database.config.tsexport default () => ({database: {host: process.env.DB_HOST,port: process.env.DB_PORT,},});
Register:
ConfigModule.forRoot({load: [databaseConfig],});
Use:
configService.get('database.host');
Use registerAs to create namespaced configs.
👉 Helps avoid key collisions and improves structure.
Example:
import { registerAs } from '@nestjs/config';export default registerAs('database', () => ({host: process.env.DB_HOST,port: process.env.DB_PORT,}));
Register:
ConfigModule.forRoot({load: [databaseConfig],});
Use:
configService.get('database.host');
👉 Partial registration (only in specific module):
ConfigModule.forFeature(databaseConfig);
Some modules need async config (e.g., DB connection).
👉 Use forRootAsync when config depends on ConfigService.
Example (TypeORM):
TypeOrmModule.forRootAsync({imports: [ConfigModule],inject: [ConfigService],useFactory: (config: ConfigService) => ({type: 'postgres',host: config.get('DB_HOST'),port: config.get('DB_PORT'),}),});
👉 Why this matters:
.envIf you want, I can turn this into a blog-style article (like your previous DI blog) or give you real-world project structure (enterprise-level) — that’s usually what interviewers care about most.