Recently, I came across a couple of Node.js projects that use NODE_ENV for defining environments for the Development, Testing, Acceptance, and Production (DTAP) pipeline. At first sight, this looks like a good idea, but I would advise against it.

What we often see is that npm modules are consuming NODE_ENV as either ‘production’ or something else. When NODE_ENV is set to ‘production’, then less logging is shown, code is optimized for performance, and some other stuff is disabled, which makes it a ‘real production code’. React.js is one of the examples in doing this through the whole codebase. Based on that, I see developers define NODE_ENV as ‘testing’, ‘acceptance’ and ‘production’ to have more logging in the test environments, less logging in the production and more performant code in the production. In my opinion, this is one of the things which you should not do.

When code moves through the DTAP pipeline, you want it to be as similar as possible on all the stages. It’s not without the reason that there are ‘testing’ and ‘acceptance’ stages, besides the ‘production’. By making different behavior inside the code and making it ‘development|testing|acceptance’ code and ‘production’ code, you can’t guarantee that the code which runs in DTA environments will run in ‘production’ the same way. Due to the subtle differences, bugs can pop up at the places where you don’t expect them.

The second reason is extra logging, which you get on non ‘production’ mode. You would say, "That’s exactly what I want in my DTA environments," but I would argue. By making explicit differentiation between DTA and P you branch your release/debug process into two different threads: debugging production code and debugging loggable code. Though if debugging of production code is not in your daily workflow, then you will probably be stuck for much longer when things will go wrong there. Often, people only learn when they’re doing something frequently. But how could we learn to trace and debug ‘production’ code if that doesn’t happen in the daily workflow? Also, don’t forget that production bug must be solved MUCH faster than any other bug. This is what makes it an even higher priority to learn to do this early in software development.

The last reason of not using NODE_ENV for defining environments applies only for isomorphic apps. This doesn’t make it less important to me. If you stick to the NODE_ENV, this means you will also have to use it in the client code. Honestly, if (NODE_ENV === 'acceptance') looks weird in the client, doesn't it? There is no node in the browser, so it makes no sense.

Here is my rule of thumb. First of all, keep your code similar as possible through all the environments, and keep NODE_ENV always on ‘production’. Second, if you have to use differentiation, make a new variable for your environment, like APP_ENV or CODE_ENV, you name it. For example, we used APP_ENV for defining our environments, because we used shared log DB and need a way to know where it comes from.