fireproofsocks
Config.exs and System.get_env/2: are values actually read at runtime?
I thought I had a handle on how Elixir configuration worked, but now I’m thinking I missed something. My memory was that the config.exs file gets read at compile-time. So if my config.exs contained the following:
# config.exs
config :myapp, :foo, System.get_env("FOO")
Then I could compile an option into it via
FOO=bar mix compile
and starting up the app would yield the value that I set at compile time, e.g.
iex -S mix
# Expected:
iex> Application.get_env(:myapp, :foo)
"bar"
But the actual result is nil. Or whatever the System ENV is set to at runtime – and the app does not re-compile.
So my question is: is config.exs actually reading values at runtime? Or is it doing something special with System.get_env/2 so it resolves at runtime? Am I going crazy? I don’t remember it working this way. Thanks for any clarifications!
Most Liked
v0idpwn
The environment is set by mix when starting up, both in compile time and when running your application. If you’re using releases, then the config is set at the point where the release is built (except for runtime.exs, which is evaluated at startup in releases as well).
al2o3cr
config.exs is still an exs file, so it’s evaluated at runtime.
My guess is that you’re remembering two similar things:
-
using
System.get_envin some places in modules will result in the “stay until the next compile” behavior you describe:defmodule SomeModule do @foo System.get_env("FOO") def foo, do: @foo endSomeModule.foowill “capture” the value from ENV at compile-time -
using
System.get_envinconfig.exswill result in a “stay until the next release” behavior for environment variables, thus the need forruntime.exs
lud
@v0idpwn I am surprised actually, I too was believing that this was compile-time only but indeed the values defined here must be available at runtime and are not stored into a file like in a release.
So the runtime execution erases the value set before compilation.
What is confusing is that if you wanted to have this config:
import Config
config :demo, foo: System.get_env("FOO")
And this code:
defmodule Demo do
@foo Application.get_env(:demo, :foo)
def foo do
@foo
end
end
You cannot call FOO=bar mix compile and then just iex -S mix and get the expected value, because iex -S mix will always trigger a recompilation. The code above will emit a warning as you should use Application.compile_env. Very different behaviour than calling @foo System.get_env("FOO") directly.
Personnally, I just put everything possible in runtime.exs.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









