Configuration Management with @nestjs/config

Table of Contents

  1. Introduction to Configuration in NestJS
  2. Why Use @nestjs/config?
  3. Installing and Setting Up @nestjs/config
  4. Using .env Files for Environment Variables
  5. Accessing Config Values in Services
  6. Configuration Namespaces and Validation
  7. Loading Custom Config Files
  8. Using ConfigService with DI
  9. Config Best Practices: Security, Scoping, and Defaults
  10. Example: Environment-Based Database Config
  11. Summary and What’s Next

1. Introduction to Configuration in NestJS

Configuration is crucial for managing different environments (development, staging, production), API keys, secrets, database URLs, and feature flags. Hardcoding such values is dangerous and unscalable. That’s where @nestjs/config shines—offering a standardized way to manage configuration in a secure and scalable way.


2. Why Use @nestjs/config?

NestJS’s @nestjs/config package:

  • Reads environment variables from .env files
  • Injects configuration using NestJS’s DI system
  • Supports multiple environments
  • Enables strong validation
  • Helps organize and centralize configuration logic

3. Installing and Setting Up @nestjs/config

Install the package:

bashCopyEditnpm install @nestjs/config

Import the module in your root module (AppModule):

tsCopyEditimport { ConfigModule } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true, // makes ConfigService available everywhere
      envFilePath: '.env', // default is .env
    }),
  ],
})
export class AppModule {}

This loads environment variables from the .env file into your application.


4. Using .env Files for Environment Variables

Your .env file might look like this:

iniCopyEditPORT=3000
DATABASE_URL=postgres://user:pass@localhost:5432/mydb
JWT_SECRET=supersecret

NestJS will now be able to access these values using the ConfigService.


5. Accessing Config Values in Services

You can inject ConfigService into any provider or controller:

tsCopyEditimport { ConfigService } from '@nestjs/config';

@Injectable()
export class AppService {
  constructor(private configService: ConfigService) {}

  getDatabaseUrl() {
    return this.configService.get<string>('DATABASE_URL');
  }
}

You can even provide defaults:

tsCopyEditthis.configService.get<number>('PORT', 3000);

6. Configuration Namespaces and Validation

To keep configuration organized, define custom configuration files as namespaces:

tsCopyEdit// config/database.config.ts
export default () => ({
  database: {
    host: process.env.DB_HOST,
    port: parseInt(process.env.DB_PORT, 10) || 5432,
  },
});

Then register it in your ConfigModule:

tsCopyEditConfigModule.forRoot({
  load: [databaseConfig],
});

To validate .env values using Joi:

tsCopyEditimport * as Joi from 'joi';

ConfigModule.forRoot({
  validationSchema: Joi.object({
    PORT: Joi.number().default(3000),
    DATABASE_URL: Joi.string().required(),
  }),
});

7. Loading Custom Config Files

You can modularize your config into separate files (e.g., auth.config.ts, db.config.ts) and load them all:

tsCopyEditConfigModule.forRoot({
  load: [dbConfig, authConfig],
});

This keeps config organized and scalable.


8. Using ConfigService with DI

ConfigService can be injected anywhere thanks to its global scope (if set):

tsCopyEditconstructor(
  private readonly configService: ConfigService
) {}

You can even inject it into factory providers or dynamic modules.


9. Config Best Practices: Security, Scoping, and Defaults

  • Never commit .env to version control
  • Use .env.example to document required variables
  • Validate all config inputs
  • Use default values to prevent crashes in dev
  • Abstract config access via helper functions when used repeatedly

10. Example: Environment-Based Database Config

tsCopyEdit// database.providers.ts
{
  provide: 'DATABASE_CONNECTION',
  useFactory: async (configService: ConfigService) => {
    const dbUrl = configService.get('DATABASE_URL');
    return createConnection({ url: dbUrl });
  },
  inject: [ConfigService],
}

11. Summary and What’s Next

The @nestjs/config package provides a powerful and flexible way to manage application configuration. It integrates deeply with NestJS’s DI system and supports validation, namespacing, and dynamic loading of config values.