Environment & Config
Configuration belongs in the environment, not in your source code. Environment variables let the same code run in development, staging, and production with different settings.
process.env
Every environment variable is available on process.env:
const port = process.env.PORT ?? 3000;
console.log(process.env.NODE_ENV); // "development" | "production" | ...
Values are always strings. Convert when you need numbers or booleans:
const debug = process.env.DEBUG === "true";
const port = Number(process.env.PORT ?? 3000);
.env Files
Locally, put variables in a .env file:
PORT=3000
DATABASE_URL=postgres://localhost:5432/app
API_KEY=super-secret
Load it with Node’s built-in support (Node 20.6+):
node --env-file=.env src/index.js
Or with the dotenv package:
import "dotenv/config";
Never Commit Secrets
Add .env to .gitignore:
.env
.env.*
!.env.example
Commit an .env.example with placeholder values so teammates know what is needed:
PORT=3000
DATABASE_URL=
API_KEY=
Validate Early
Fail fast if required config is missing:
function requireEnv(name) {
const value = process.env[name];
if (!value) throw new Error(`Missing env var: ${name}`);
return value;
}
const apiKey = requireEnv("API_KEY");
Better to crash at startup than to discover a missing secret in production.
Production
Hosting platforms set env vars through their dashboard or CLI. Never bake secrets into the image or repo. In CI, store them as encrypted secrets.
Best Practices
- Commit
.env.example— Document required variables. - Validate on boot — Crash early, clearly.
- Scope secrets — Only give a service the variables it needs.
- Rotate keys — Treat leaked secrets as compromised.
Common Mistakes
- Committing
.env— Secrets end up in git history. - Hardcoding config — Forces code changes between environments.
- Assuming strings —
"0"and"false"are truthy. - Logging secrets — Do not print tokens or keys.