Skip to main content

dotenv

What is dotenvโ€‹

dotenv is an npm package that loads environment variables from a .env file into process.env. BSD-2-Clause licensed, currently at version 16.4.7 (~35โ€“40M weekly npm downloads, ~19,400 GitHub stars). It is the de facto standard for managing environment variables during local development for Node.js applications.

Key mechanic: dotenv never overwrites existing environment variables โ€” if a variable is already set in the process environment, the .env value is silently ignored. This means CI/CD platforms can inject environment variables that safely override local .env files.

Why we recommend itโ€‹

  • Universal adoption โ€” virtually every Node.js project uses it or a tool that wraps it (Vite, Next.js, and others use it internally)
  • Zero-friction local setup โ€” add a .env file, call dotenv.config(), done
  • Non-destructive loading โ€” never overwrites variables already in process.env, so production secrets injected via CI/CD always take precedence
  • Tiny and dependency-free โ€” no transitive dependencies; negligible install footprint
  • Pairs cleanly with .env.example โ€” enables the convention of committing a documented template while keeping real secrets out of version control

When to useโ€‹

  • Local development for any Node.js application or server
  • CLI tools and one-off Node.js scripts that need environment-specific config
  • Backend services where environment variables are loaded at startup (dev only โ€” use platform injection in production)

When NOT to useโ€‹

  • Production servers โ€” inject environment variables at the platform level (Cloud Run, Vercel, GitHub Actions) rather than shipping a .env file
  • Vite projects (frontend) โ€” Vite has built-in dotenv support with no install required (see Environment Variables)
  • Client-side / browser code โ€” there is no process.env in the browser; never import dotenv in frontend code
danger

Never ship a .env file to production or commit it to version control. .env files commonly contain API keys, database credentials, and tokens. Add .env and .env.local to .gitignore immediately when setting up a project.

.env file formatโ€‹

dotenv parses UTF-8 KEY=VALUE files.

.env
# Comments start with #
DATABASE_URL=postgresql://localhost:5432/myapp

# Quoted values: single or double quotes are stripped
API_SECRET="my secret value"

# Multiline values require double quotes
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----"

# Whitespace around = is trimmed
PORT = 3000
tip

Use .env.example as a template. Commit a .env.example file with every key your project needs but with blank or dummy values. This documents required variables for new developers without exposing real secrets. The actual .env is always gitignored.

Basic usageโ€‹

Call dotenv.config() (or use the import side-effect) before any code that reads process.env.

server.js
// CommonJS
require('dotenv').config();

// ESM โ€” side-effect import (no function call needed)
import 'dotenv/config';

// After either of the above, process.env is populated:
const port = process.env.PORT ?? 3000;
caution

dotenv.config() must run before any process.env reads. Calling it after a module that already read process.env at import time means those variables will be undefined. Put the dotenv call at the very top of your entry file.

tip

To force-load .env values over variables already set in process.env (useful when testing specific configs locally), pass override: true:

require('dotenv').config({ override: true });

Why over alternativesโ€‹

  • vs Node.js --env-file flag (Node.js 20.6+) โ€” the native flag (node --env-file=.env server.js) requires no package at all and is the right choice for simple scripts on Node 20+. dotenv remains the better choice for shared project configs that need .env.example tooling and ecosystem integrations.
  • vs dotenv-flow โ€” dotenv-flow adds multi-file cascade loading (.env, .env.local, .env.development, etc.) for plain Node.js projects. Use it only if you need environment-specific .env files for a Node.js backend not using Vite or Next.js.
  • vs cross-env โ€” a different tool entirely: cross-env sets inline env vars in npm scripts cross-platform and is in maintenance mode. It solves a different problem.

For full framework-specific env var handling, see Environment Variables.

Resourcesโ€‹

  • dotenv on GitHub โ€” motdotla/dotenv
  • dotenv on npm
  • dotenv-expand โ€” adds ${VAR} substitution; used internally by Vite and Next.js
  • Environment Variables โ€” .env naming conventions, Vite's env handling, GitHub Actions secrets, and production secrets management
  • Web Security Essentials โ€” why secrets must never be embedded in frontend bundles
  • Vite โ€” build tool with built-in dotenv support (no install needed for Vite projects)