Library configuration - multi-instance

Sorry, I only used MIX_ENV as an example. You could use any environment variable. I would also argue that choosing between Sandbox and DBAdapter is only a compile time concern if your lib is compiling the adapter into the Repo module. Otherwise the adapter you use will still be determined at runtime. For instance if you do this:

# config.exs
config :my_lib, MyRepo,
  adapter: Sandbox

defmodule MyRepo do
  defp adapter do
    Application.get_env(:my_lib, MyRepo)[:adapter]
  end
end

The adapter is still chosen at runtime. At that point there’s not a lot of difference between calling Application.get_env and passing the adapter module as an argument like: Repo.start_link(adapter: Sandbox). If you pass the adapter as an argument then you have no coupling to Application at all, which is nicer for end users.

That said, I’m not necessarily opposed to using config.exs for configuring the adapter. If you go that route then you need to make sure you don’t do something like this:

config :my_lib, adapter: Sandbox

That configuration will be global across all instances of your library and will stop your users from running multiple instances of your library. This is the mistake that most elixir libraries make. Instead, you’ll need to use a configuration like:

config :my_lib, MyInstance,
  adapter: Adapter

The user will need to understand how to wire all of that up correctly. The situation gets even more gnarly if other libraries want to use your library. In that scenario, the user will have to configure instances of your library that they’re using, and configure instances that the other library is using.

In the end, passing arguments is always more flexible than trying to use Application configs, and its why I default to just passing arguments in most cases. Using config.exs has its place but it’s much less flexible and I think it should be used sparingly. The majority of libraries that use config.exs shouldn’t.