I've had rare cases of needing nested data structures in the environment. My solution was to specify them as JSON strings and load the value in code. It works.
- If your configuration has more than 5-10 options then env vars become a mess while a configuration file is more maintainable
- Nested configuration / scoping is a mature advantage of configuration files
- You can reload configuration files whereas you can't reload environment variables during runtime
- A configuration file is a transparent record of your configuration and easier to backup and restore than env variables. Env variables can be loaded from many different locations depending on your os.
- In configuration files you can have typed values that are parsed automatically with env variables you need to parse them yourself. This is just a difference not that bad for env variables per se.
Programs reconfigurable at runtime are by far rarity, as that's generally pretty hard thing to do. But yes, just have a config file, ENVs are nice as a backup for small apps, but never as only way
It's definitely nice when it does but it's also a whole lot of complexity to add to the code. You have to re-create all structures relying on configs, reconnect if needed, clear all previous ones, but only after any ongoing processing of requests received before the reload signal finishes.
Some go half-way, like HAProxy where it does spawn a new process but that process just binds with SO_REUSEPORT and signal old one to close the socket and finish all remaining connections. So you effectively get hitless reload, it's just that old process is the one finishing in-flight requests
Yeah, it def adds complexity but if you want it used in real world applications, it’s a must-have. With only env vars, it’s an impossibility to ever have (without supporting infrastructure and processes), which was the point I was trying to make.
Hardly. "Real world applications" need to tolerate single node failure anyway so reload functionality doesn't add all that much. Some system daemons, sure, them not working for a second can be disruptive so it is worthy endeavor there, but the amount of added complexity is nontrivial and the added complexity scales with apps' own complexity.
It's a bit different for desktop apps, as restarting app every time you change some config options would be far bigger PITA than some server app.
Yes. Env vars beat constants but have stunted our thinking because we know deep down it's not a great idea to have too too many.
Config files are better, but can lead to the mess described here and typically only give us crude axes for overriding.
It's time for us to embrace & tame the complexity. If you use a feature flag tool already, you know what it's like to target different values based on rules.
If I want to experiment with changing the http timeout for specific calls from a single service in a single region I should be able to roll that out.
It's time to expand our brains and bring this feature flag style thinking to the rest of our configuration.
> If I want to experiment with changing the http timeout for specific calls from a single service in a single region I should be able to roll that out.
...why ? how often you do it ? What actual app feature it fills ? Why would you throw permanent code at something that you need to do once or twice?
That kind of thing is FAR better served as customizable hooks (loadable .so/.dll, maybe even attached Lua interpreter) rather than bazillion random flags for everything and checks cluttering code.
For anything more than trivial configurations it can be nice to commit them to source control, giving some reversion capabilities, and easy replication on other projects.
I'm thinking of things like config for nginx, Apache, Kubernetes, etc.