How to Set Up a Dotenv File in Node.js Using the dotenv NPM Package
To set up a dotenv file in Node.js, install the dotenv package via npm, create a .env file with KEY=VALUE pairs, and call require('dotenv').config() at the top of your entry file to load the variables into process.env.
Node.js applications frequently require sensitive configuration data—such as database URLs and API keys—that should never be hard-coded. The dotenv npm package provides a robust solution for managing these secrets by loading them from a local .env file into process.env at runtime. While the Node.js runtime itself includes a minimal built-in parser for environment files (implemented in src/node_dotenv.h and src/node_dotenv.cc within the nodejs/node repository), the dotenv package offers greater flexibility and explicit control from your JavaScript code.
How the dotenv Package Works
When you invoke require('dotenv').config(), the package reads your .env file line-by-line, parses each KEY=VALUE pair, and injects them into the process.env object exposed by Node.js core (defined in src/node_process_methods.cc). This happens synchronously before your application logic executes, ensuring that environment variables are available immediately. Values are always stored as strings, so you must manually convert them to numbers or booleans when needed.
Step-by-Step Guide to Setting Up dotenv in Node.js
Install the dotenv NPM Package
Add the package to your project dependencies using your preferred package manager:
npm install dotenv --save
Create the .env File
At the root of your project, create a file named .env. Each line should follow the KEY=VALUE syntax. Lines beginning with # are treated as comments.
# Database configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
# API credentials
API_KEY=super-secret-token
Load Environment Variables in Your Application
Import and configure dotenv at the very top of your entry file (e.g., index.js or app.js) to ensure variables are loaded before any other modules execute:
// index.js
require('dotenv').config();
// Application code starts here
console.log('Database host:', process.env.DB_HOST);
Access Variables via process.env
Retrieve values anywhere in your codebase using process.env.KEY. Remember to handle type conversion since all values are strings:
const dbHost = process.env.DB_HOST;
const dbPort = Number(process.env.DB_PORT);
const apiKey = process.env.API_KEY;
Advanced Configuration Options
Load Custom File Paths
For projects with multiple environments (development, testing, production), specify a custom path using the path option:
require('dotenv').config({ path: './config/production.env' });
Handle Loading Errors
The config() method returns an object containing an error property if the file cannot be read. Implement error handling to fail fast during startup:
const result = require('dotenv').config({ path: './config/.env' });
if (result.error) {
console.error('Failed to load environment variables:', result.error);
process.exit(1);
}
Type Conversion and Validation
Create helper functions to safely convert environment strings to typed values:
require('dotenv').config();
function asNumber(key, fallback) {
const value = process.env[key];
return value !== undefined ? Number(value) : fallback;
}
const maxConnections = asNumber('MAX_CONN', 10);
const debugMode = process.env.DEBUG === 'true';
Security Best Practices for dotenv Files
Never commit your .env file to version control. Add it to your .gitignore file immediately. The Node.js repository itself follows this pattern, as seen in deps/undici/src/.gitignore.
# .gitignore
.env
.env.local
.env.*.local
Provide a .env.example file in your repository that documents the required keys without exposing actual secrets:
# .env.example
DB_HOST=
DB_PORT=
API_KEY=
Summary
- Install the
dotenvpackage vianpm install dotenvto manage environment-specific configuration. - Create a
.envfile at your project root usingKEY=VALUEsyntax, keeping it out of version control as specified in the Node.js source patterns. - Load variables early by calling
require('dotenv').config()at the top of your entry file, which populatesprocess.envusing the same parsing concepts found in Node.js core files likesrc/node_dotenv.cc. - Access values anywhere via
process.env, converting strings to numbers or booleans as needed, and use thepathoption to support multiple environments.
Frequently Asked Questions
What is the difference between the dotenv package and Node.js built-in --env-file flag?
The dotenv npm package provides programmatic control from JavaScript, allowing you to load custom files, handle errors gracefully, and execute logic before your app starts. Node.js also ships with a native .env parser (implemented in src/node_dotenv.h and src/node_dotenv.cc) that activates when using the --env-file CLI flag. The native approach requires no dependencies but offers less flexibility for dynamic file selection within your code.
Can I use multiple .env files for different environments?
Yes. Instead of relying on a single .env file, pass the path option to config() to load environment-specific files such as .env.development or .env.production. Call this early in your application bootstrap to ensure the correct variables are available before other modules execute.
Why are my environment variables undefined after calling config()?
This typically occurs when the .env file is missing, the path option points to the wrong location, or the file contains syntax errors. The config() method returns an object with an error property if loading fails. Always check this property or verify the file exists at the expected path relative to your working directory.
Should I commit my .env file to version control?
No. The .env file should never be committed to Git or any version control system, as it typically contains sensitive credentials. Add .env to your .gitignore file immediately. The Node.js repository follows this security practice in paths like deps/undici/src/.gitignore. Instead, commit a .env.example file that lists the required keys without values to document the configuration schema for other developers.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s https://instagit.com/install.md