
Build and launch your apps in minutes
Topics
What is the use of dotenv?
How do I set up a dotenv file?
Should I install dotenv as a dev dependency?
How do I access an .env file in Node?
Learn the best practices of using npm dotenv, know how it manages environment variables in Node.js. Load configuration from a
.envfile to keep sensitive keys safe, work with multiple environments, and simplify project setup without exposing credentials in your code.
Hard-coding API keys or database passwords into your code invites security issues. npm dotenv solves this by loading environment variables from .env file, keeping sensitive data separate from your application code. This guide explains how to set it up and manage environment-specific variables across different environments.
One of the simplest ways to load environment variables into your application code is by using the zero-dependency dotenv module from npm.
When your app starts, you can preload dotenv using:
node -r dotenv/config your_script.js
This loads environment variables from a .env file into process.env before your script runs. The result: your app gets a clean set of environment-specific values without hard-coding sensitive data like API keys.
What’s the use of dotenv?
It lets you separate configuration from your code, following the Twelve-Factor App principle. A .env file stores environment variables in your project’s root directory. This makes it safer to store secrets—like API keys, database passwords, or production-specific configs—outside version control.
First, install the module:
npm install dotenv
Should you install as a dev dependency?
If you need dotenv in both development and production (e.g., loading DB credentials in both environments), install it as a normal dependency. Only use --save-dev if it’s strictly for local development.
In your application code (CommonJS syntax):
const dotenv = require('dotenv'); dotenv.config();
Or, in ES modules:
import dotenv from 'dotenv'; dotenv.config();
Here, calling dotenv.config() parses your .env file and injects the variables into process.env.
Tip: If you’re using ECMAScript Modules (ESM) in Node.js (i.e., import instead of require), then:
You must call
dotenv.config()before importing any other module that uses environment variables. Otherwise, those modules will load before your environment is set andprocess.envwill be empty in those files. —- LinkedIn Post
You can tell dotenv to load a different env file without modifying your code:
This is ideal for managing environment-specific variables (e.g., , ).
returns an object with:
You can reference one variable inside another by also using :
.env
index.js
Multiline variables are also supported, making it safe to store private keys without breaking parsing. If things don’t load as expected, you can enable debug output:
Want to manage your projects even faster? Try Rocket.new — instantly create, configure, and launch ready-to-code apps with dotenv pre-setup.
A typical workflow might load development database credentials locally, and production credentials on a server by pointing to a different file. For example:
This separation keeps secrets out of your code and version control.
Once dotenv is configured, variables are available via :
This allows you to keep configuration outside of code—especially useful in cloud deployments, where env vars can be set without editing source files.
.env
index.js
Both quoted and unquoted values work fine.
Using dotenv to manage environment variables is straightforward, but applying best practices ensures security, maintainability, and scalability in different environments (development, staging, production). Below are the key recommendations:
.env files often contain sensitive information like API keys, database credentials, or private tokens.
Always add to your file:
Instead of committing the file, share it securely with your team through password managers or secure configuration services.
Maintain separate files like:
Specify the correct file in dotenv.config():
This avoids overwriting production settings with development values.
Prefix variables with the project or service name to avoid conflicts.
This becomes especially important when multiple projects run on the same machine or server.
Avoid nesting structures in files — dotenv does not parse objects or arrays natively.
Example:
Use a validation library (like envalid or joi ) to ensure all required environment variables are present and correctly formatted.
Maintain a file containing all keys without sensitive values:
This helps with onboarding new developers and avoids “it works on my machine” issues.
If a default is needed, set it in .env or handle it gracefully:
In long-running processes, environment variables are loaded only at startup. If you change .env mid-run, you’ll need to restart the app to apply updates.
Now you know how to:
Set up for development and production, enable debug mode if keys fail to load, and enjoy a safer, more maintainable configuration system.
.env.development.env.productiondotenv.config()parsederrordotenv-expand.envprocess.envnode -r dotenv/config.env.development.env.test.env.productionDOTENV_CONFIG_PATHHELLO=hello world
GREETING="hello world again"
.env.gitignore.envAPI_URL=https://api.example.com
API_TIMEOUT=5000
.env.exampleAPI_URL=
API_KEY=
DATABASE_URL=
require('dotenv').config().env.env.env# Preload dotenv before your script
node -r dotenv/config your_script.js
# Preload dotenv with a custom env file path
DOTENV_CONFIG_PATH=./custom.env node -r dotenv/config your_script.js
BASE_URL=http://localhost
API_URL=${BASE_URL}/api
import dotenv from 'dotenv';
import dotenvExpand from 'dotenv-expand';
const myEnv = dotenv.config();
dotenvExpand.expand(myEnv);
DEBUG=true node -r dotenv/config your_script.js
# Development
DOTENV_CONFIG_PATH=.env.development node -r dotenv/config app.js
# Production
DOTENV_CONFIG_PATH=.env.production node -r dotenv/config app.js
const path = require('path');
const dotenv = require('dotenv');
const result = dotenv.config({
path: path.resolve(__dirname, '.env'), // default is .env in project root
encoding: 'utf8',
debug: process.env.DEBUG === 'true'
});
if (result.error) {
console.error('Error loading .env:', result.error);
} else {
console.log('Parsed keys:', Object.keys(result.parsed));
}
console.log(process.env.NODE_ENV);
console.log(process.env.API_KEY);
import dotenv from 'dotenv';
dotenv.config();
console.log(process.env.HELLO); // hello world
console.log(process.env.GREETING); // hello world again
echo ".env" >> .gitignore
.env.development
.env.staging
.env.production
require('dotenv').config({ path: '.env.production' });
APP_DB_HOST=localhost
APP_DB_USER=root
const envalid = require('envalid');
const { str, num } = envalid;
envalid.cleanEnv(process.env, {
API_URL: str(),
API_TIMEOUT: num({ default: 5000 })
});
const port = process.env.PORT || 3000;