A repository of bitesize articles, tips & tricks
(in both English and French) curated by Mirego’s team.

Meaningful config keys in Elixir projects

When working with environment variables, it’s a good pattern to store them in Elixir’s config files (Config).

However, it’s up to the developer to choose where to store those values in the configuration.

Nothing stops us from writing this perfectly fine code:

# config/runtime.exs
config :my_app, :third_party,
  base_url: System.get_env("THIRD_PARTY_BASE_URL"),
  secret_key: System.get_env("THIRD_PARTY_SECRET_KEY")

# lib/my_app/third_party.ex
defmodule MyApp.ThirdParty do
  def fetch_data do
    # Use base_url() and secret_key() here
  end

  defp base_url, do: Application.get_env(:my_app, :third_party)[:base_url]
  defp secret_key, do: Application.get_env(:my_app, :third_party)[:secret_key]
end

The :third_party atom in which we store our values is pretty arbitrary. We should take advantage of the fact that we can use a module name (which is basically an atom) as the configuration key.

This adds an extra meaning to our configuration. We’re saying “We want to configure X” by using X as the key instead of another atom that doesn’t represent anything:

 # config/runtime.exs
-config :my_app, :third_party,
+config :my_app, MyApp.ThirdParty,
   base_url: System.get_env("THIRD_PARTY_BASE_URL"),
   secret_key: System.get_env("THIRD_PARTY_SECRET_KEY")

 # lib/my_app/third_party.ex
 defmodule MyApp.ThirdParty do
   def fetch_data do
     # Use base_url() and secret_key() here
   end

-  defp base_url, do: Application.get_env(:my_app, :third_party)[:base_url]
-  defp secret_key, do: Application.get_env(:my_app, :third_party)[:secret_key]
+  defp base_url, do: Application.get_env(:my_app, __MODULE__)[:base_url]
+  defp secret_key, do: Application.get_env(:my_app, __MODULE__)[:secret_key]
 end

Both examples are fine, but in my opinion the second one is a little bit better 🙂