Many developers start with hard-coded config and secrets in either JSON or JavaScript files, and while this works, it poses a security risk as any developer with code access can potentially view secrets such as production database credentials and API keys.
If you're currently configuring your applications like this, don't worry, you're not alone! Most developers eventually realize that hard-coding credentials isn't the way to go, and begin looking for a more secure alternative in the form of a secrets manager.
This is exactly we created Doppler—giving developers an easy to use secrets manager for Node.js applications that centralizes secrets storage with an easy to use CLI for injecting secrets as environment variables.
Environment variables are considered the best way to configure applications, with the main benefits being:
Using environment variables for configuring Node.js (and even JavaScript front-end) apps enables your application to be built and deployed anywhere, whether it's for local development on macOS, a container in a Kubernetes Pod, or modern Node.js hosting environments such as Vercel, Heroku, Netlify, Cloudflare Workers, and AWS Lambda.
Specifically, you could use environment variables to:
Note: If you haven't worked much with environment variables on the commandline, check out our ultimate guide for using environment variables in Linux and Mac.
Now that you know why environment variables are the best way to configure Node.js and JavaScript apps, let's explore the syntax for getting, setting, and loading environment variables.
When your Node.js application starts or a script is run, a new (child) process is created which inherits the environment variables from the parent process. Node parses the environment variables, creating a process.env object where every key and value is a string.
Using an interactive Node terminal, we can inspect the contents of process.env:
Now you know how environment variables in Node.js are populated, let's learn how to work with them.
Accessing an environment variable from process.env is no different to that of a regular object:
The one notable difference with the process.env object, is that every key and value will always be a string. This is because environment variables themselves can only ever be strings.
If a value you're accessing from an environment variable needs to be a non-string type, you must parse or cast it yourself, e.g. casting a PORT environment variable to an integer:
While the syntax for accessing an environment variable is simple, more thought is required when deciding how environment variables are parsed and used, e.g. how to handle the case when a required variable is not supplied.
Because JavaScript won't error when accessing a key that doesn't exist in process.env, you'll need to design a solution for how your application will behave when a required environment variable is not supplied.
One option is to use the ok method from the assert module:
If executed without setting the API_KEY environment variable, you'll be greeted with something like the following:
Why use assert.ok? Because we want our application to throw an exception and exit if it's not configured properly.
You might be thinking "that's kinda ugly" which personally I'm ok with, as it should be a rare exception that your app is incorrectly configured.
If you wanted to handle this case with nicer output, you could use something similar to:
Now if executed without setting the API_KEY environment variable, the output would be:
[error]: The "API_KEY" environment variable is required
Whichever you choose is personal preference—the main thing being that you're handling the case of a missing required environment variable strictly and correctly.
You can have a default value returned if an environment variable doesn't exist by using the || (OR) operator:
So while the code to provide default values is simple, you should try to avoid defaults in your application code, the reasons of which I'll cover next.
The reason for avoiding defaults for environment variables is simple: A single source of truth should exist for any app config and secret value.
When debugging your application because it is misconfigured (and trust me, it's only a matter of time), the removal of defaults means every config or secret value was supplied by environment variables—that's your source of truth.
Default values in application code can make debugging a misconfigured application more difficult, as the final config values will likely be a combination of hard-coded default values and environment variables.
Make life easier for your future self (and team) by requiring all app config and secret values be set explicitly using environment variables.
Setting or creating a new environment variable in Node.js is the same as setting a key on a standard object, except Node will implicitly convert any non-string value to a string.
It's recommended to convert a value you wish to set as an environment variable to a string first, as future versions of Node may throw an exception if a non-string value is assigned.
When it comes to changing Node.js environment variables, there are two things to be aware of:
Deleting a Node.js environment variable is the same as deleting a key from a standard object:
Deleting an environment variable only affects the current script or application and doesn't affect the parent process.
As an aside, if you're confused as to why deleting a key from process.env is always true (even once the key has been deleted), you're not alone.
It's because it will only return false if the property is "non-configurable", such as Math.PI or a property created as a result of calling Object.defineProperty() or Object.freeze().
Check out the Mozilla docs for the delete operator if you'd like to know more.
As an application grows in size and complexity, so does the number of environment variables needed for app config and secrets.
A popular but problematic and insecure solution is to store the list of environment variables in a .env file and use the npm dotenv package to parse the .env file and populate the process.env object.
While .env files are simple and easy to get started with, they also cause a new set of problems such as:
These are just some of the reasons why we recommend moving away from .env files and using an environment variable manager such as Doppler instead.
Doppler provides an access-controlled dashboard for managing environment variables in every environment with an easy-to-use CLI for accessing config and secrets that work for every language, framework, and platform.
You can check out our Mandalorion GIF sample application and deploy it to Vercel to see how to use Doppler for managing environment variables for a Node.js application.
The NODE_ENV environment variable originally came from the Express web framework and was used to alter internal behavior, such as caching templates and using less verbose logs if NODE_ENV was set to production.
It has since become a popular Node.js convention for conditional logic based on the environment type, for example:
Awesome work! Now you know how to use environment variables in Node.js for application config and secrets.
Although we're a bit biased, we encourage you to try using Doppler for managing your Node.js environment variables, and it's free to get started with our Developer plan (unlimited projects, secrets, and users).
To see Doppler in action, check out the Mandalorion GIF sample application.
I hope you enjoyed the post and if you have any questions or feedback - chat with the Doppler team in our Community forum.
To delete an environment variable in Node.js, treat it like deleting a key from a standard object using the delete operator. This change affects only the current script or application and doesn't impact the parent process.
Environment variables in Node.js are considered a secure way to configure applications, as they prevent secrets like database credentials from being leaked into the source code and allow applications to be deployed in different environments without code changes.
Using .env files for environment variables in Node.js is discouraged for larger, more complex applications due to the risk of accidentally committing sensitive data to source control, exposing the .env file publicly, and challenges in keeping .env files in sync across environments. It's recommended to use an environment variable manager instead.
Trusted by the world’s best DevOps and security teams. Doppler is the secrets manager developers love.