Built-in --env-file Support
Node.js 20.6 added the --env-file flag, which loads a .env file and populates process.env before your code runs — without any npm packages. This is the built-in equivalent of calling require('dotenv').config() at the top of your entry file. Node 22 extended it with --env-file-if-exists (silently ignores missing files) and support for multiline values.
Basic usage
# Load .env before running your app (Node 20.6+): node --env-file=.env server.js # With watch mode: node --watch --env-file=.env server.js # Load a non-default env file: node --env-file=.env.staging server.js # Multiple --env-file flags — later files override earlier ones: node --env-file=.env --env-file=.env.local server.js # Node 22: silently continue if the file doesn't exist: node --env-file-if-exists=.env.local server.js
.env file format
# .env — same format as dotenv:
DATABASE_URL=postgres://localhost:5432/mydb
PORT=3000
NODE_ENV=development
# Quoted values (required for values with spaces or special characters):
GREETING="Hello, World!"
REGEX_PATTERN='^d{4}-d{2}-d{2}$'
# Comments:
# This is a comment
DATABASE_POOL_SIZE=10 # inline comment (stripped)
# Multiline values (Node 22+):
PRIVATE_KEY="-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9...
-----END PRIVATE KEY-----"--env-file vs dotenv — comparison
Feature |
|
|
|---|---|---|
Install required | None — built in |
|
Node version | 20.6+ | Any |
Variable expansion | No | With |
Programmatic control | CLI flag only |
|
Override existing env vars | No — existing env wins |
|
Multiple files | Multiple |
|
Missing file behavior | Error (use | Silent by default |
Works in all environments | Requires passing flag | Works anywhere |
NODE_OPTIONS for scripts that call node indirectly
# If you run tests or scripts via npm/npx and they spawn node internally, # use NODE_OPTIONS to pass the flag: NODE_OPTIONS="--env-file=.env" npm test NODE_OPTIONS="--env-file=.env" npx jest # Or set it in package.json scripts: # "test": "NODE_OPTIONS='--env-file=.env' jest"
Recommended development workflow
# .env (git-ignored) — developer's local overrides: DATABASE_URL=postgres://localhost:5432/mydb_dev REDIS_URL=redis://localhost:6379 PORT=3000 # .env.example (committed) — documents all required variables: DATABASE_URL= REDIS_URL= PORT=3000 JWT_SECRET= # package.json: # "dev": "node --watch --env-file=.env src/server.js" # "test": "NODE_OPTIONS='--env-file=.env.test' node --test src/**/*.test.js"