274

This is my app that I'm currently running on production.

var app = express();
app.set('views',settings.c.WEB_PATH + '/public/templates');
app.set('view engine','ejs');
app.configure(function(){
    app.use(express.favicon());
    app.use(express.static(settings.c.WEB_PATH + '/public'));
    app.use(express.bodyParser());
    app.use(express.cookieParser());
    app.use(express.methodOverride());
    app.use(express.session({
            cookie:{ domain:"."+settings.c.SITE_DOMAIN, maxAge:1440009999},
            secret:'hamster',
            store: r_store,
            }));
    app.use(useragent.express());
    app.use(flash());
    app.use(passport.initialize());
    app.use(passport.session());
});

Now I've learned about NODE_ENV and want to use it. How can I do this?

Dave Mackey
  • 4,306
  • 21
  • 78
  • 136
TIMEX
  • 259,804
  • 351
  • 777
  • 1,080
  • In the your case i assume what you can use is `app.configure('development', ...)` or "production" to set certain settings only for development or production environments. See http://expressjs.com/api.html#app.configure – Andreas Hultgren Jun 07 '13 at 07:19
  • Similar question https://stackoverflow.com/questions/9198310/how-to-set-node-env-to-production-development-in-os-x – Michael Freidgeim Jan 04 '21 at 12:06

5 Answers5

502

NODE_ENV is an environment variable made popular by the express web server framework. When a node application is run, it can check the value of the environment variable and do different things based on the value. NODE_ENV specifically is used (by convention) to state whether a particular environment is a production or a development environment. A common use-case is running additional debugging or logging code if running in a development environment.

Accessing NODE_ENV

You can use the following code to access the environment variable yourself so that you can perform your own checks and logic:

var environment = process.env.NODE_ENV

Assume production if you don't recognise the value:

var isDevelopment = environment === 'development'

if (isDevelopment) {
  setUpMoreVerboseLogging()
}

You can alternatively using express' app.get('env') function, but note that this is NOT RECOMMENDED as it defaults to "development", which may result in development code being accidentally run in a production environment - it's much safer if your app throws an error if this important value is not set (or if preferred, defaults to production logic as above).

Be aware that if you haven't explicitly set NODE_ENV for your environment, it will be undefined if you access it from process.env, there is no default.

Setting NODE_ENV

How to actually set the environment variable varies from operating system to operating system, and also depends on your user setup.

If you want to set the environment variable as a one-off, you can do so from the command line:

  • linux & mac: export NODE_ENV=production
  • windows: $env:NODE_ENV = 'production'

In the long term, you should persist this so that it isn't unset if you reboot - rather than list all the possible methods to do this, I'll let you search how to do that yourself!

Convention has dictated that there are two 'main' values you should use for NODE_ENV, either production or development, all lowercase. There's nothing to stop you from using other values, (test, for example, if you wish to use some different logic when running automated tests), but be aware that if you are using third-party modules, they may explicitly compare with 'production' or 'development' to determine what to do, so there may be side effects that aren't immediately obvious.

Finally, note that it's a really bad idea to try to set NODE_ENV from within a node application itself - if you do, it will only be applied to the process from which it was set, so things probably won't work like you'd expect them to. Don't do it - you'll regret it.

Pang
  • 9,564
  • 146
  • 81
  • 122
Ed_
  • 18,798
  • 8
  • 45
  • 71
  • 6
    In Express 4, `app.configure()` has been removed. The [Express 4 migration guide](http://expressjs.com/guide/migrating-4.html) recommends to "use `process.env.NODE_ENV` or `app.get('env')` to detect the environment and configure the app accordingly." – Chris Bartley Oct 27 '14 at 13:56
  • Good spot - I've updated the answer to reflect this. – Ed_ Oct 27 '14 at 14:04
  • 3
    I think it is best to use app.get('env') because if the environment is undefined node defaults to dev where as just checking the variable yourself gives undefined – light24bulbs Nov 09 '14 at 20:26
  • 13
    Good point - I added a note to highlight the default. However my personal feeling is that you shouldn't use `app.get('env')` for precisely that reason. It covers up that this important variable is not set - making things seem inconsistent when you access it from outside of express. Furthermore I think it's less harmful to have debug code accidentally _not running_ on a development environment than it is to have it accidentally _running_ on a production environment. – Ed_ Nov 10 '14 at 10:07
  • 9
    I've measured the effects of omitting setting NODE_ENV in express applications. It defaults to `development` which - among other things - means that templates will be reprocessed for every request. The consequence is a performance gain or drain of ~75% between production and development when using Jade. I've also created a blog post on that http://apmblog.dynatrace.com/2015/07/22/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/ – DanielKhan Jul 22 '15 at 14:56
  • 9
    I think for express projects, besides "production" and "development", you at least need another one "test" for running the automated tests. You might want to use a different DB for populated test data. – dawnstar May 02 '16 at 02:41
  • 2
    You can use [**cross-env**](https://github.com/kentcdodds/cross-env) inside npm script to set the NODE_ENV variable. Example : `"build": "cross-env NODE_ENV=production webpack --config build/webpack.config.js"` – Ronan Quillevere Jun 16 '17 at 12:53
  • I was using "dev" instead of "development" and it wasn't accepting the value – Vaulstein Nov 23 '21 at 06:47
31

NODE_ENV is an environmental variable that stands for node environment in express server.

It's how we set and detect which environment we are in.

It's very common using production and development.

Set:

export NODE_ENV=production

Get:

You can get it using app.get('env')

MarredCheese
  • 17,541
  • 8
  • 92
  • 91
Alireza
  • 100,211
  • 27
  • 269
  • 172
15

I assume the original question included how does Express use this environment variable.

Express uses NODE_ENV to alter its own default behavior. For example, in development mode, the default error handler will send back a stacktrace to the browser. In production mode, the response is simply Internal Server Error, to avoid leaking implementation details to the world.

Randy Hudson
  • 1,600
  • 1
  • 12
  • 11
5

Disclaimer: This answer may annoy quite a few people, but it has to be spoken. No offense meant, please try to consider a point of view wider than a developer's point of view.

To business:

This is an environment variable first popularized by the express framework, and later "leaked" to be used in different packages and services.

Specifically in express - when the value is anything that is not production - the library enters a development mode that is more forgiving, more debuggable, logs more and consumes more memory.

More common quirks is libraries of view-rendering or middlewares of view-rendering skip cache on non-production modes, expecting the files to be modified by developer between refreshes.

Eventually, npm started using this setting, so it's not going anywhere.

This is one of the confusing points in ops for nodejs and express. This is basically an anti-pattern, coupling a behavior with a name of an environment.

What's wrong with that?

  • What if I don't want my tests to run in a mode that is different from production?
  • What if I have few cloud environments with different names, all of which need to function like produciton?

The name of the variable pushes many ops people to a trap, where they fill in NODE_ENV the name of the environment, and are surprised when they get from the same distribution different behavior and performance from what they get in production.

The result is that as a consultant I see that most teams had to come with a 2nd variable like OVERRIDE_ENV, NODE_ENV_NAME, NODE_ACTUAL_ENV and many more nonsense of that sort, and keep fighting with the ops that intuitively associate a name like NODE_ENV with the name of the environment...

A better name would have been EXECUTION_MODE, but that's a littsy bitsy too late to change now, so we're stuck with that, and unfortunately, not only in express...

bfontaine
  • 18,169
  • 13
  • 73
  • 107
Radagast the Brown
  • 3,156
  • 3
  • 27
  • 40
  • Sure, the name's not great, but it isn't exactly `ENV_NAME` which seems to be how you're implying most people read it. I would certainly not be creating any environment variables named `NODE_ENV_ACTUAL` or anything like that - if I wanted to name my server I'd just use `SERVER_NAME`... Not sure this post is helpful at all - the only part I agree with is that it could be annoying to change behaviour based on this variable, but any library worth its salt will use this to set sensible defaults and allow explicit overrides for all of the settings. – Ed_ Apr 14 '22 at 11:03
  • 2
    that's exactly the problem I'm pointing at - this practice couples behavior with environment. What if you want the behavior of one environment in another, e.g. - you want in **QA** the exact same behavior like **prod**? Then you are forced to name your **QA** `production` - and that's wrong. Same if you want to stop **prod** from using the so-called production express features. – Radagast the Brown Apr 19 '22 at 08:24
  • We've been experimenting with two env vars...something like DEPLOYED_STAGE and DEPLOYED_ENV. So we might have STAGE set to 'staging' and ENV set to 'local' or 'aws' or whatever. This does introduce more complexity, but on the other hand it more accurately reflects what people are often trying to do with a single name. Not sure if we'll stick with this convention or not. – Dustin Wyatt Aug 09 '22 at 17:14
  • 1
    FYI, I agree with this answer, but I'm not sure it's actually an answer to the asked question. – Dustin Wyatt Aug 09 '22 at 17:15
  • It's pretty standard practice for frameworks and libraries to alter behaviour based on the environment they are running in. This is done for convenience. It's just not feasible to write a custom full configuration for every environment, that would mean a dev would have to study the full configuration mechanism of a framework. So frameworks toggle on sensible defaults. So how do you suggest doing it in a way that makes sense to ops? Use 'development' to enable development features and any other env name to not have those features? – Avin Kavish Aug 19 '22 at 05:49
  • I think it was specifically named, `NODE_ENV` for this reason. The actual environment good go into the `ENV` or `ENVIRONMENT` variables. – Avin Kavish Aug 19 '22 at 05:55
  • @AvinKavish - the point is that anybody that is not a nodejs developer that knows the peculiarities of this discussion (like ops often are, or on-call guys, or support) is too likely to be mislead and make a mistake. – Radagast the Brown Aug 21 '22 at 09:34
1

Typically, you'd use the NODE_ENV variable to take special actions when you develop, test and debug your code. For example to produce detailed logging and debug output which you don't want in production. Express itself behaves differently depending on whether NODE_ENV is set to production or not. You can see this if you put these lines in an Express app, and then make a HTTP GET request to /error:

app.get('/error', function(req, res) {
  if ('production' !== app.get('env')) {
    console.log("Forcing an error!");
  }
  throw new Error('TestError');
});

app.use(function (req, res, next) {
  res.status(501).send("Error!")
})

Note that the latter app.use() must be last, after all other method handlers!

If you set NODE_ENV to production before you start your server, and then send a GET /error request to it, you should not see the text Forcing an error! in the console, and the response should not contain a stack trace in the HTML body (which origins from Express). If, instead, you set NODE_ENV to something else before starting your server, the opposite should happen.

In Linux, set the environment variable NODE_ENV like this:

export NODE_ENV='value'

Rein
  • 477
  • 2
  • 7