Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addressing some issues around dotenv #222

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/blog/pattern-to-reconsider/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,12 @@ await axios.put(`${process.env.USER_SERVICE_URL}/api/user/${post.userId}/increme

**📊 How popular:** 21,806,137 downloads/week!

**🤔 Why it might be wrong:** Dotenv is so easy and intuitive to start with, so one might easily overlook fundamental features: For example, it's hard to infer the configuration schema and realize the meaning of each key and its typing. Consequently, there is no built-in way to fail fast when a mandatory key is missing - a flow might fail after starting and presenting some side effects (e.g., DB records were already mutated before the failure). In the example above, the blog post will be saved to DB, and only then will the code realize that a mandatory key is missing - This leaves the app hanging in an invalid state. On top of this, in the presence of many keys, it's impossible to organize them hierarchically. If not enough, it encourages developers to commit this .env file which might contain production values - this happens because there is no clear way to define development defaults. Teams usually work around this by committing .env.example file and then asking whoever pulls code to rename this file manually. If they remember to of course
**🤔 Why it might be wrong:** Dotenv is so easy and intuitive to start with, so one might easily overlook fundamental features: For example, it's hard to infer the configuration schema and realize the meaning of each key and its typing. Consequently, there is no built-in way to fail fast when a mandatory key is missing - a flow might fail after starting and presenting some side effects (e.g., DB records were already mutated before the failure). In the example above, the blog post will be saved to DB, and only then will the code realize that a mandatory key is missing - This leaves the app hanging in an invalid state. On top of this, in the presence of many keys, it's impossible to organize them hierarchically. <strike>If not enough, it encourages developers to commit this .env file which might contain production values - this happens because there is no clear way to define development defaults.</strike> .env is meant to define development and development only. We expressely [recommend against committing your .env file to code](https://github.com/motdotla/dotenv#should-i-commit-my-env-file). Teams usually work around this by committing .env.example file and then asking whoever pulls code to rename this file manually. Recently, the same people that pioneered dotenv are [extending it with syncing features](https://github.com/dotenv-org/dotenv-vault) to avoid this work around.

**☀️ Better alternative:** Some configuration libraries provide out of the box solution to all of these needs. They encourage a clear schema and the possibility to validate early and fail if needed. See [comparison of options here](https://practica.dev/decisions/configuration-library). One of the better alternatives is ['convict'](https://github.com/mozilla/node-convict), down below is the same example, this time with Convict, hopefully it's better now:

Doesn't sharing a `config.js` file that should NOT be committed to code have the same risk as committing a .env file?

```javascript
// config.js
export default {
Expand Down