I agree with you completely, and I think that releases are the path to follow when you have multiple servers and/or you can dedicate time to create your build workflow.
First of all, you need a build environment that suits your needs, which ends up with an extra machine / docker container / something else.
Also, you need to take care of not using
Mix.env anywhere inside your production code and including all libraries you are using on the release (i have seen cases of a library that has no application and isn't included by default on the releases) or your app may crash.
On the other side, you can use docker images with your Erlang version, pre-fetched libraries, pre-compiled application and assets (if you have) for production and just run it using
mix, which give you a mostly-accurate snapshot of your software at that point.
Problems of using containers for this? That you will be storing big container images instead of small tarballs. But on the other hand the deployment is easier to maintain and enough for many cases if you don't run a fail-proof software (no downtimes, only hot code updates) and doing eager loading is not a decisive point.
At the end, I think it depends deeply on each use case: if you have time enough to prepare a build workflow, if your application really needs it, if you like/dislike Dockerized applications.....
I have really enjoyed reading the thoughts about this topic, thanks guys!