Consistent environment variables #26213
Replies
|
IIRC crypto used to have some examples of 2, the env var wasn't looked at until crypto was required, and it wasn't at startup, but maybe its gone now. It allowed node app startup code to set env vars, which some found useful. I'm torn. On the one hand, I love consistency and predictability. On the other hand, it can be useful to set env vars at runtime to make things happen. I would say that ideally the current value would be always used, except that for perf reasons, values need caching, and we can't catch every way that env vars can be updated and cause dynamic changes inside node.js, that would be more work than is worthwhile for such a fringe benefit. |
|
@nodejs/tsc is this something we might want to address (as in find a rule how to deal with these consistently)? It came up here #19464 (comment) |
|
I would agree with @sam-github’s stance on this – ideally, variant 3 is the best thing to do, but if that’s not feasible one of the others will have to do. |
|
I would expect the behavior of 3. If we want to do 1 we have to be careful not to access the environment variables prior to pre-execution so that we still have an environment-independent point to create v8 snapshots (I am working on only making process.env available until then and making sure it is not available during the execution of bootstrap/node.js) |
|
Note that the env object is slow to access, and most of the caching (2) was added for speed reasons. Environment variable should be checked at startup, and then never accessed again. I do not think we would be setting a good example if we did 3. Environment variables are set when a process is launched and they cannot be changed at runtime. I think 1 is the best choice. I'll be supportive of 3, if we can prove it will not regress performance. |
|
They can, and there's a very popular package that does it: https://www.npmjs.com/package/dotenv |
You can change the Node.js representation of the environment variables. You can change Essentially, I see the "binary invocation" as a discrete moment where ENV variables are collected and passed it to the process. They are called "environment" variables for a reason: they are the variables of the outside environment. Once a process as sampled them at startup (unix), those are the external representation. Node.js already works in this way for IMHO it's the responsibility of an application to sample those ENV variables as soon as possible, and be done with it. An application is not supposed to change them at runtime, because by definition of env variable they are defined at startup time (whatever late that startup time is). It's good to have them editable to make |
|
This just came up again with #26187. What do you all think about adding a flag to opt-in to only allowing to set And actually there are more cases then the ones I listed originally. As there is a difference between e.g., checking Case 1 is also ambiguous by not guaranteeing to be loading up front when Node.js starts. It could still be changed before that code part is loaded. |
|
If we postpone the access to any |
|
@joyeecheung that would also be a good option but |
|
@BridgeAR I would not expect such a flag to gain significant usage, both because it is incompatible with how existing code uses |
|
@addaleax I think of it as a safeguard against code inside of a dependency tree and also against a mistake done by someone from the same company. So I would not expect it to be used by the average developer but mainly by companies that want to make sure their environment variables are not manipulated. |
|
@mcollina it likely works fine because most users won't ever manipulate environment variables during runtime. Especially not one that they do not have full control over. However, that possibility does exist and it's possible to cause very weird behavior by changing some We also control a couple of things in Node.js itself with envs and some of it is critical such as There are of course many less critical situations but handling environment variables as "set once" prevents such situations without a real downside. Setting a env with a different value than the original one should throw in error in such case while using the same value should be ignored. |
I think that's a bug, and we should change this behavior to read that flag once at require time. |
Not sure what this means. The past can't be changed, but the env doesn't go away after process start, its still there, and it can be changed with http://man7.org/linux/man-pages/man3/setenv.3.html, which we use Lines 94 to 106 in 4804a18 There is no huge problem ATM, except that some env vars if changed will effect the current process, and some if changed won't, and we can't tell from the docs which are which. |
Not to side track the issue, but I'm not sure about that point. There are valid use cases, such as setting |
|
I too am guilty of writing to Now if there were a way to forbid such actions in dependencies (e.g. anything loaded from a Can anyone come up with a valid use case of a dependency writing to |
I think the package mentioned in #26213 (comment) is one. |
Native add-on use case: node-heapdump knows about a |
Yes:
|

AFAIK we have no rule when to check for environment variables.
I see three possibilities to do so:
So far we mainly use
3and some times1. There is probably also usage of2but I could not find any by briefly searching through the code base.Do we want to consolidate the behavior to always follow the same rules (that might not be possible in all cases but probably in most)?
To give examples for all three behaviors: