When building a Node.js app, you’ll often see a file called .env. At first, it may look confusing, but it’s actually one of the most important parts of managing your application properly.
What is a .env File?
A .env file is used to store configuration values for your application.
Example:
PORT=5000
DB_URL=mongodb://localhost:27017/myapp
JWT_SECRET=mySecretKeyInstead of hardcoding these values inside your code, we keep them separately.
This makes the application:
Cleaner
Easier to manage
More secure
Different for development and production
Why Not Store Everything Directly in Code?
Bad example:
const password = "mypassword123";Imagine pushing this to GitHub by mistake.
Using .env it is safer:
DB_PASSWORD=mypassword123Then inside Node.js:
process.env.DB_PASSWORDHow Node.js Reads .env
Node.js does not automatically read .env files.
We usually use a package called dotenv.
Install it:
npm install dotenvThen load it:
require("dotenv").config();Now you can access values like this:
const port = process.env.PORT;Important: Never Upload
.envto GitHubAdd this to
.gitignore:.env
Your .env may contain private keys, and keeping them private is very important.
Priority of Environment Variables in Node.js
This is where many beginners get confused. Environment variables can come from multiple places.
For example:
System environment variables
.envfilePM2 ecosystem config
Docker
Hosting provider settings
Node.js follows a priority order.
Basic Priority Order
Usually, the priority looks like this:
System Environment Variables
PM2 Environment Variables
.envFileDefault values in code
Example:
Suppose your .env contains:
PORT=3000But you start your app like this:
PORT=8000 node server.jsThen the app will use 8000
Because system variables override .env.
Using .env with PM2
If you use PM2, environment handling becomes even more important.
PM2 allows you to define environment variables directly inside the ecosystem config.
module.exports = {
apps: [
{
name: "my-app",
script: "./server.js",
env: {
NODE_ENV: "development",
PORT: 3000
},
env_production: {
NODE_ENV: "production",
PORT: 8000
}
}
]
};Running PM2 in Production
pm2 start ecosystem.config.js --env productionPM2 will use env_production values.
PM2 vs .env - Which Has Priority?
If both contain the same variable:
.env
PORT=3000PM2:
env: {
PORT: 8000
}Then the final value will usually be:
8000Because PM2 environment variables override .env.
Best Practice
A good setup is:
.env
Store local/private values.
PM2
Store deployment/runtime environment settings.
Example
# .env file
DB_URL=mongodb://localhost/test
JWT_SECRET=abc123PM2:
env_production: {
NODE_ENV: "production",
PORT: 8000
}This keeps things organised.
Common Mistakes
1. Forgetting to Load dotenv
require("dotenv").config();Without this, .env values won’t load.
2. Adding Spaces
❌ Wrong:
PORT = 3000✅ Correct:
PORT=30003. Uploading .env to GitHub
Always use:
.env4. Using Different Variable Names
❌ Wrong:
DATABASE_URL=abc✅ Code:
process.env.DB_URLThis will return undefined.
Production Tip
In real production servers, many developers don’t even use .env files.
Instead, they use:
Server environment variables
Docker secrets
Cloud platform settings
PM2 configs
This is usually more secure.
Final Thoughts
.env Files make Node.js applications cleaner, safer, and easier to manage.
Once you understand the priority system between:
.envSystem variables
PM2
Default values
You’ll avoid many deployment issues.
Start simple, keep secrets out of code, and organise your environment variables properly from the beginning.
That small habit saves a lot of trouble later.


