process.env: How to Use Environment Variables in Node

Working with environment variables is a great way to configure different configurations of your Node.js application. Many cloud hosts like Heroku, Azure, AWS now.sh, etc., use node environment variables. Likewise, node.js modules use environment variables.

Hosts, for example, will set the PORT variable that specifies on which port the server should listen to work properly. In addition, modules might have different behaviors (like logging) depending on the value of the NODE_ENV variable.

process.env

The process.env is a global variable injected by Node.js at runtime for your application to use, and it shows the state of the system environment your app is in when it starts at runtime in our app to use.

It describes the state of the system environment of our app when it starts.

For example, if the system has the PATH variable set, this will be accessible to you through the process.env.PATH variable you can use to check where binaries are located and make external calls to them if required.

Why environment variable is essential in Node

When we write the code, we can never know where our app can be deployed. So if we require the database in development, we spin up its instance and link to it via a connection string, something like 127.0.0.1:3306.

However, when deploying it to the server in production, we might need to link it to the remote server, 32.22.2.1.

Now, we can write the code linking the database using the process.env file.

const connection = new Connection(process.env.DB_CONNECTION_STRING);

Specifying an external service dependency allows us to link to the remote load-balancer-protected database cluster, which can scale independently of an app and enable us to have multiple instances of our app alone of a database service.

Basics of process.env

Accessing environment variables in Node.js is supported out of the box. When your Node.js process boots up, it will automatically provide access to all the existing environment variables by creating the env object as a property of the process global object.

I am using Node.js version 11. Now, if you have not installed Node.js, then please install it.

After that, create a folder, a file called app.js, and add the following code.

console.log(process.env);

Now, go to the terminal and hit the following command.

What is process.env in Node.js

The above code should output all the environment variables of which this Node.js process is aware.

If we want to access one specific variable, access it like any object property. For example, let’s access the PORT property.

console.log(process.env.PORT);

You will see the undefined output because we have defined a specific port yet.

Cloud hosts like Heroku or Azure use the PORT variable to tell you which port your server should listen to for the routing to work correctly.

Therefore, the next time you set up the web server, you should determine the port to listen on by checking PORT first and giving it a default value otherwise.

See the following code.

// app.js

const app = require('http').createServer((req, res) => res.send('Ahoy!'));
const PORT = process.env.PORT || 4000;

app.listen(PORT, () => {
  console.log(`Server is listening on port: ${PORT}`);
});

In the above code, we have created the HTTP server, which runs on either the defined port in the .env file or, by default, 4000.

Run the file and see the output.

Basics of process.env

Since process.env is an ordinary object, we can easily set/override the values.

It is explicitly loading variables from the .env file.

We have two levels to work with server provisioning: 1) infrastructure and 2) application levels. We can either set an environment through the application-level logic or use the tool to provide an environment.

A standard application-level tool is dotenv, which allows us to load the environment variables from a file named .env. Then, we can install it via NPM using the following command.

npm install dotenv --save

Afterward, add the following line to the top of your entry file.

require('dotenv').config();

The above code will automatically load the .env file in the root of your project and initialize the values. It will skip any variables that have already been set.

You should not use the .env file in your production environment; instead, set the values directly on the host. Therefore, you might want to wrap the config statement in the if-statement.

if (process.env.NODE_ENV !== 'production') {
  require('dotenv').config();
}

Now, create a file called .env and add the following line of code inside that .env file. First, you must make the .env file at the root of your project folder.

PORT = 3000

Now, write the following code inside the app.js file.

// app.js

if (process.env.NODE_ENV !== 'production') {
  require('dotenv').config();
}

const app = require('http').createServer((req, res) => res.send('Ahoy!'));
const PORT = process.env.PORT || 4000;

app.listen(PORT, () => {
  console.log(`Server is listening on port: ${PORT}`);
});

Run the server, and you will see the server is running on PORT: 3000 and not 4000.

While this is convenient for development needs, it is considered harmful to couple the environment with our application, so keep it out by adding .env to your .gitignore file.

We can use the deployment managers tools like PM2, Docker Compose, and Kubernetes to specify an environment at an infrastructure level.

PM2 uses an ecosystem.yaml file where you can specify the environment using the env property.

apps:
  - script: ./app.js
    name: 'my_application'
    env:
      NODE_ENV: development
    env_production:
      NODE_ENV: production
    ...

Docker Compose likewise allows the environment property to be specified in the service manifest.

version: "3"
services:
  my_application:
    image: node:8.9.4-alpine
    environment:
      NODE_ENV: production
      ...
    ...

Kubernetes has an equivalent to the env property in the pod template manifest, which allows us to set the environment:

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
  name: my_application
spec:
  ...
  template:
    spec:
      env:
        - name: NODE_ENV
          value: production
        ...

We are using the process.env.* correctly results in applications that can be tested quickly and deployed/scaled elegantly. So, we have seen process.env in Node.js very deeply in this article.

That’s it for this tutorial.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.