Stop 05 · Backend with Node.js & ExpressTopics · 8/8

Environment Variables

Part of the Full Stack Developer Roadmap

In short

The same code runs on your laptop, in staging and in production. What changes is config: ports, database URLs, secret keys. Environment variables carry it in without touching the code.

Configuration values (database URLs, API keys, secrets) kept outside your codebase and injected via `process.env` — critical for keeping secrets out of version control on both frontend and backend.

The mascot cricket captain reads a note card from the ground staff, with the pitch and stumps behind.

Think of it like this

The pitch report before every match

Same team, same players, but before each match the captain reads the ground staff's note: dry pitch, dew expected, short boundary. He adjusts the plan without changing the team. Environment variables are that note for your app.

Watch it happen

Start, read config, shut down cleanly

Terminal
Node process
Your app

PORT=8080 node app.js

1/6The shell starts Node and passes PORT along in the process's environment.

The big ideas

What you need to know

process describes your program

process.argv holds command-line arguments, process.env the environment, process.pid the process id, process.cwd() the folder.

Everything is a string

"3000" needs Number(), and "false" is a truthy string. Convert and compare explicitly.

.env files for local dev

Node 20.6+ loads one with node --env-file=.env app.js. Commit a .env.example, never the real .env.

Fail fast on bad config

Check required variables at startup and exit with code 1 if one is missing, instead of crashing later.

See it in code

Walk through the code

js
1// run: node --env-file=.env server.js2import http from "node:http";3 4const port = Number(process.env.PORT ?? 3000);5const debug = process.env.DEBUG === "true"; // "false" would be truthy!6if (!process.env.DATABASE_URL) {7  console.error("DATABASE_URL is missing");8  process.exit(1);9}10 11const server = http.createServer((req, res) => res.end("ok\n")).listen(port);12console.log(`pid ${process.pid} on port ${port}, debug=${debug}`);13 14process.on("SIGTERM", () => {15  server.close(() => process.exit(0));16});

1/3Load .env, then convert values: a number for the port, a real boolean for debug.

.env holds lines like PORT=8080 and DATABASE_URL=postgres://... Add it to .gitignore and commit a .env.example with dummy values instead.

Save yourself the pain

Common mistakes

Oops

Writing if (process.env.DEBUG) with DEBUG=false and wondering why debug mode is on.

Do this instead

Every env value is a string, and "false" is truthy. Compare explicitly: process.env.DEBUG === "true".

Oops

Committing .env with real API keys to GitHub.

Do this instead

Add .env to .gitignore before the first commit. If a key leaks, rotate it at once. Deleting the commit isn't enough.

Your mission

Config like a pro

~20 min

Quick check

You start your app with PORT=8080 node app.js. What is typeof process.env.PORT?

Go deeper

  1. 1Use a `.env` file with `dotenv` for local backend configuration.
  2. 2Add `.env` to `.gitignore` before your first commit.
  3. 3Learn the difference between backend secrets (never exposed) and frontend env vars (bundled into public code).

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge