BugForge
All lessons
Node.js · 15/19 5 min

Config and environment variables

process.env is all strings, || vs ??, defaults, and secrets read before they exist.

Everything is a string

process.env.DEBUG = false;
if (process.env.DEBUG) { … }          // runs: "false" is a truthy string

const debug = process.env.DEBUG === "true";
const port = Number(process.env.PORT ?? 3000);
const limit = Number.parseInt(process.env.RATE_LIMIT ?? "100", 10);

|| vs ??

const retries = Number(process.env.RETRIES) || 3;   // ❌ RETRIES=0 becomes 3
const raw = process.env.RETRIES;
const retries2 = raw === undefined ? 3 : Number(raw);   // ✅ 0 stays 0

?? only falls back on null/undefined; || also replaces 0, "" and false.

Read config at the right time

// ❌ evaluated once at import; if the test sets the env later, SECRET is undefined forever
const SECRET = process.env.JWT_SECRET;

// ✅ read when needed, or load env before requiring the app
const secret = () => process.env.JWT_SECRET;

One config module

// config.js
function required(name) {
  const v = process.env[name];
  if (!v) throw new Error(`Missing env var ${name}`);
  return v;
}
module.exports = {
  port: Number(process.env.PORT ?? 3000),
  jwtSecret: required("JWT_SECRET"),
};

Fail fast at startup instead of signing tokens with undefined.

Secrets

  • Never commit .env; commit .env.example with fake values.
  • Don't log the whole process.env or a config object that holds secrets.
Next in Node.js
Don't block the event loop