Phoenix: module constant can't read from runtime environment variables

Hi, I was having issue with reading environment variable in my Phoenix app.
I’m using distillery for building and already using REPLACE_OS_VARS=true when running my app.

All application env wasn’t evaluated to read my system environment variables.

Later, I found that I call Application.get_env/2 for constant assignment didn;t work as expected. But if I move assignment to be normal variable inside my method/function it works.

Supposed I have
config.exs

use Mix.Config

config :ex_aws,
  access_key_id: ["${AWS_KEY}", :instance_role],
  secret_access_key: ["${AWS_SECRET}", :instance_role],
  s3: [region: "${AWS_REGION}"]

If I declared constant like this
aws_client.exs

    defmodule Uploader.AwsClient do
        @aws_options %{acl: :public_read}
        @base_url Application.get_env(:uploader, :asset_url)
        @bucket  Application.get_env(:uploader, :bucket_aws)

      def upload(file) do
    ....

It won’t be have the correct value
while
aws_client.exs

    defmodule Uploader.AwsClient do
        @aws_options %{acl: :public_read}

      def upload(file) do
        base_url = Application.get_env(:uploader, :asset_url)
        bucket = Application.get_env(:uploader, :bucket_aws)

will read environment variables properly

Is there anyone can expain this behaviour

1 Like

Module constants are set at compile time, so when the release is generated. If you want “constants” that can be set at runtime, you can make a function:

def base_url(), do: Application.get_env(:uploader, :asset_url)
7 Likes

Could you give me link or documentation that module constants are set on compile time instead of runtime?

1 Like

nevermind, I got this :smiley:

thanks @Nicd

3 Likes