What's the current recommended way to check current environment dev/prod in a Phoenix module?

This has changed a few times over the years for me so I’m just checking what the latest recommended way is to check for env :dev or :prod?

I have a Phoenix context module and I want to do something only if it’s currently :prod.

defmodule MyApp.Analytics.Posthog do
  def schedule_event(event_name, params) do
    if :prod do
      # send the event
    end
  end
end

See A universal way to detect environment in Phoenix? - #11 by soup

2 Likes

I’ve seen and used that pattern before, I really don’t like it. It smells of “architecture astronaut” to me especially at the start of the project. I get the merits of it, but I don’t want to overcomplicate things.

Can I reliably depend on a module attribute with Mix.env at compile time? I’m using mix release in a Dockerfile?

@current_env Mix.env()

defmodule MyApp.Analytics.Posthog do
  def schedule_event(event_name, params) do
    if @current_env == :prod do
      # send the event
    end
  end
end

I feel like you’ve likely thought of and discarded this option, but is there a reason that normal application config wouldn’t work for you here?

defmodule MyApp.Analytics.Posthog do
  def schedule_event(event_name, params) do
    if Application.get_env(:my_app, :send_events) do
      # ...
    end
  end
end

# runtime.exs

config :my_app, send_events: config_env() == :prod

One benefit of this pattern is that it makes it easier to test individual features in development using an env var flag.

config :my_app,
  send_events: config_env() == :prod || System.get_env("DBG_SEND_EVENTS") == "true"
2 Likes

I thought of that but there’s that little additional indirection layer I really don’t like. Is there a way to just directly use that config_env value of :prod in my module?

you could add an helper func in your Application for easier access in other parts of the code?

defmodule MyApp do
  def env do
    Application.fetch_env!(:my_app, :env)
  end
end

I’ve used it but with an unix environment variable which can override the app config param (through a docker startup call)

AFAIK config_env stand-alone is only useable during compile time. Most of the above is also documented here Config — Elixir v1.14.2

The indirection is a benefit not a downside. Your application should care only if it‘s configured to do things one way or another. The mix env is just a means of giving a name to a set of configurations or ways of building that configuration. If you don‘t to that you‘ll need to have a separate mix env per (used) sets of code permutations, which is not a good idea.

2 Likes