Per-Environment Config and Safe Defaults
Layer development, staging, and production overrides while keeping sensible fallback defaults.
Why Per-Environment Config Matters
An enterprise NestJS API runs in several places at once: a developer's laptop, a staging cluster, and production. Each needs different values: database URLs, log levels, feature flags, third-party keys.
- Development favors convenience: verbose logs, local DB, relaxed timeouts.
- Staging mirrors production but with test data and safer credentials.
- Production favors safety and performance: strict logging, real secrets, hardened defaults.
The goal of this lesson is to layer these environments so a single codebase behaves correctly everywhere, while keeping sensible fallback defaults when a value is missing.
The NODE_ENV Signal
The conventional way to tell environments apart is the NODE_ENV variable. Nest itself, and most tooling, read it to decide behavior.
A robust app should never assume NODE_ENV is set. Treat a missing value as development so a fresh checkout still runs, but never silently treat an unknown value as production.
type AppEnv = 'development' | 'staging' | 'production';
function resolveEnv(raw: string | undefined): AppEnv {
const value = (raw ?? 'development').toLowerCase();
if (value === 'production' || value === 'prod') return 'production';
if (value === 'staging' || value === 'stage') return 'staging';
return 'development';
}
console.log(resolveEnv(undefined)); // development
console.log(resolveEnv('PRODUCTION')); // production
console.log(resolveEnv('stage')); // stagingAll lessons in this course
- Schema-Validated Env with Joi and forRoot
- Namespaced Config with registerAs
- Loading Secrets from HashiCorp Vault and AWS SSM
- Per-Environment Config and Safe Defaults