Bingo.

The author's title is unfortunate: "Never use environment variables for configuration"

Not everyone is writing CLI scripts. Some are writing multi-environment software for the web. Some people care about git and distributed teams.

Let's say you backup and migrate a db which has config in the db. Well your other environment is using the wrong config! Now you're possibly using prod SMTP credentials and sending notifications to the wrong people because all you wanted to do was have live content and do some testing or show debug messages because you're on a test environment.

Web frameworks which have the HTTP host in the database drive me nuts. Why do you need that? Your webserver is responding on a domain name. Why do some store the absolute url in the db. It makes no sense. For the 3 people that want to serve up domainA.com but have all links readily be domainB.com maybe that makes sense.

Don't get burned people. For most things, just ignore this article, keep your secrets out of version control and keep your code ready to deploy to multiple environments. Decouple that. Your app should be able to work with various configurable services (SMTP, push notifications, database, etc) and you don't want that config in version control.

So either a file that's outside of version control with variables you set per environment or actual server environment variables.

Environment variables in many web languages are just namespaced globals. Still better than global variables. They serve a purpose.

The author has this:

int first_argument;

int second_argument;

void add_numbers(void) {
return first_argument + second_argument;
}

While it helps the author's agenda, that's not a legitimate example.

A real example would be a service provider which a developer would understand to have the sole purpose of pulling from environment or config values to initialize.

You wanted a Twilio client? Well, we know it needs some keys. Use environment variables. Boom. Everywhere you ask for this Twilio client you get the same instance with the config that that environment needs.

This is not a problem. It works well. Better than any alternative.

Author also says this "Environment variables is exactly this: mutable global state."

For some CLI applications maybe. But for web languages this is not accurate. Some languages, yes, you can mutate the env variables at runtime. But your code shouldn't rely on any mutable env vars. You can load those env vars into a config. Even cache it. Not allow mutations. Many modern frameworks support this or you could implement it yourself.

And if you have a CLI that really needs to be explicit about the environment vars to run? And not be different the next time you call it with no env vars? Well maybe take those as arguments?

Plenty of CLI apps that store config in json and have a wizard to set those credentials. AWS CLI as an example.

Now you got JSON as the author wanted. That can work across platforms. But guess what? You work on multiple clients and hosts and next time you call it? Well you might not be expecting that it had config for another client or app.

Same problem. The state was mutated. You called it again. You potentially got burned. Now you have to do the CLI wizard to reconfigure. Or you pass in explicit params if allowed.

Definitely a consideration if you are writing such a program. Do you make it explicit with arguments and options? Load from ENV vars? Have some CLI wizard and save to JSON?

The author's suggestion of JSON is no reason to toss out ENV vars. Just solves slight differences between Windows and Unix. Which is why you can program a CLI wizard if you care about that problem.

We don't need to say no to env vars because we want CLI app users across different platforms to have the exact same API. Setting up a JSON file is really lame to use a program. Which is why you see cli wizards when you run them.

Or things like "aws configure". And you still have CLI arguments and options availabe.