Environment variables are variables that are set outside of a program. Using a .env file for keeping secrets (that we don’t want accidentally leaked out) is standard practice, but finding a strategy for managing .env files between multiple environments on a single machine isn’t so obvious.

When we talk about overcoming this challenge using NodeJS, we talk about using the dotenv package and one of the solutions is creating two or more .env files for each environment specifically. 

In this article, I will talk about three environments, so first we need to create three .env files: .env.development .env.testing , and .env.production file: 

(A quick aside: environment variables are, by convention, generally written in all caps.)


DATABASE_URL=postgres://country:[email protected]/country_dev


DATABASE_URL=postgres://country:[email protected]/country_test


DATABASE_URL=postgres://country:[email protected]/country_prod

As it is mentioned before, we will use the dotenv package to load environment variables into the project, more precisely, the process.env interface. dotenv can be configured to read environment variables from files other than .env which is precisely what we need.

To use dotenv , first install it using the command: npm i dotenv

In this solution, we will have .env file that will be used as a controller and the place where we change the environment on which we want to run our tests and whose variables need to be loaded. For this purpose, I have set up a development environment:


After all .env files have been created, let’s create the main config file where we set up loading of specific environment variables and let the dotenv package know what file to load. We can name it env.config.ts

// import necessary packages
import dotenv from 'dotenv';
import path from 'path';

type Environment = "development" | "test" | "production"

class Env {

 private dotEnvDefault = ".env";
 private dotEnvTest = ".env.test";
 private dotEnvDevelopment = ".env.development";
 private dotEnvProduction = ".env.production";

 constructor() {

 init() {

   // configure dotenv with the configuration in the .env file
     path: path.resolve(process.cwd(), this.dotEnvDefault),

   // and get the environment specified
   const environment = this.getEnvironment();

   // then load the name of the specific environment file
   const envFile = this.getEnvFile(environment);

   // and the last, re-configure dotenv with environment we send
     path: path.resolve(process.cwd(), envFile),

 getEnvFile(environment: Environment): string {
   switch (environment) {
     case "development":
       return this.dotEnvDevelopment;
     case "test":
       return this.dotEnvTest;
     case "production":
       return this.dotEnvProduction;

 getEnvironmentVariable(variable: string): string {
   return process.env[variable];

 getEnvironment(): Environment | null {
   return this.getEnvironmentVariable("NODE_ENV") as Environment;

 // check which environment is set up
 isDevelopment() {
   return this.getEnvironment() === 'development';

 isTest() {
   return this.getEnvironment() === 'test';

 isProduction() {
   return this.getEnvironment() === 'production';


const env = new Env();
export default env;

The last one is to create a file where all the above will be used. I will name it smoketest.tswhich contains a smoke test for an application we need to run in a specific environment. As we can see below, first of all, we need to make imports and initialize the environment; after that, I add variables to check which environment is set up, which could be used later in tests. 

import env from './env.config'
const environment = env.getEnvironment();
const isDevelopment = env.isDevelopment();
const isTest = env.isTest();
const isProduction = env.isProduction();

To sum up, with this solution, we can make as many .env  files as we need for testing purposes. There should be awareness that the dotenv package is loaded twice: first, to find out which environment we are currently in, then again to load the proper environment variable file. This is all handled in the env.config.ts file. By using this solution, it is always necessary to create a .env file that will point out where the variables we need are contained. In .env.development/testing/production files, we can add different environment variables that are specific for some environments, like: USER, DATABASE_URL, PORT, etc. 

“Load more .env files for different environments using NodeJS” Tech Bite was brought to you by Sanela Mešić, Test Engineer at Atlantbh.

Tech Bites are tips, tricks, snippets or explanations about various programming technologies and paradigms, which can help engineers with their everyday job.

Protractor parallel execution
QA/Test AutomationTech Bites
May 12, 2023

Protractor parallel execution

Why Parallel Testing? When designing automation test suites, the ability to run tests in parallel is a key feature because of the following benefits: Execution time - Increasing tests efficiency and, finally, faster releases Device compatibility - There are many devices with various versions and specifications that need to be…
Introduction to GraphQL
QA/Test AutomationTech Bites
May 11, 2023

Introduction to GraphQL

In today's Tech Bite topic, we will get familiar with GraphQL and explain its growth in popularity in recent years as the new standard for working with APIs. What is GraphQL? GraphQL stands for Graph Query Language. It is an API specification standard and, as its name says - a…
IQR in Automation Testing
QA/Test AutomationTech Bites
April 25, 2023

IQR in Automation Testing: Unleashing the Data Analytics Potential

Usually, when people talk about statistics, they think only about numbers, but it is much more.  Statistics is an irreplaceable tool in different fields like data analysis, predictive modeling, quality control, scientific research, decision-making models, etc. Overall, statistics provide a valuable toolset for understanding, describing, and making predictions about data,…

Leave a Reply