Real World Example

Config per Environment on a Real Deployment

A team running ShopEase on a GCP VM or Kubernetes keeps one codebase and changes only environment variables. Secrets come from a secret manager in production, a .env file locally.

laptop      .env.local  -> NODE_ENV=development  DATABASE_URL=localhost
CI tests    env vars    -> NODE_ENV=test         DATABASE_URL=postgres-service (docker)
staging     secrets     -> NODE_ENV=production   DATABASE_URL=staging-db
production  secrets     -> NODE_ENV=production   DATABASE_URL=prod-db, JWT_SECRET from Secret Manager

src/app.module.ts

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import databaseConfig from './config/database.config';
import paymentsConfig from './config/payments.config';
import { validate } from './config/env.validation';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      cache: true,
      ignoreEnvFile: process.env.NODE_ENV === 'production',   // prod: real env vars only
      envFilePath: [`.env.${process.env.NODE_ENV ?? 'development'}.local`, '.env'],
      load: [databaseConfig, paymentsConfig],
      validate,
    }),
  ],
})
export class AppModule {}

Example

NODE_ENV=production PORT=8080 DATABASE_URL=postgresql://... JWT_SECRET=... node dist/main

Example output

[Nest] 1  - LOG [NestFactory] Starting Nest application...
[Nest] 1  - LOG [InstanceLoader] ConfigModule dependencies initialized +9ms
[Nest] 1  - LOG [NestApplication] Nest application successfully started +41ms