Releases & Deployment
A release bundles the ERTS (runtime), your compiled code and dependencies — no Elixir install needed on the server.
44.1 Mix releases
A release bundles the ERTS (runtime), your compiled code and dependencies — no Elixir install needed on the server.
Files: rel/env.sh.eex, rel/vm.args.eex, config/runtime.exs.
MIX_ENV=prod mix release
_build/prod/rel/my_app/bin/my_app start # foreground
_build/prod/rel/my_app/bin/my_app daemon # background
_build/prod/rel/my_app/bin/my_app remote # attach a remote IEx
_build/prod/rel/my_app/bin/my_app eval "MyApp.Release.migrate()"
_build/prod/rel/my_app/bin/my_app stopdef project do
[releases: [my_app: [include_executables_for: [:unix], applications: [runtime_tools: :permanent], steps: [:assemble, :tar]]]]
end44.2 Docker
Phoenix generates one with mix phx.gen.release --docker.
FROM hexpm/elixir:1.18.1-erlang-27.2-debian-bookworm-20250101-slim AS build
WORKDIR /app
ENV MIX_ENV=prod
RUN mix local.hex --force && mix local.rebar --force
COPY mix.exs mix.lock ./
RUN mix deps.get --only prod && mix deps.compile
COPY . .
RUN mix compile && mix release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y libstdc++6 openssl libncurses6 locales && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=build /app/_build/prod/rel/my_app ./
CMD ["bin/my_app", "start"]44.3 Platforms
Fly.io (first-class clustering), Gigalixir, Render, Heroku, Kubernetes (+ libcluster), bare metal/VMs (+ systemd).
44.4 Hot code upgrades
The BEAM can load new module versions without stopping (two versions coexist: current & old). Full release upgrades use appup/relup files (via tools like castle or distillery-style tooling). Most teams prefer rolling/blue-green deploys, but hot upgrades are available for systems that must never stop. In development, recompile() and Phoenix code reloading use the same mechanism.
🧪 Part III Exercises
Implement a key-value store as a raw process (spawn/receive), then as an Agent, then as a GenServer.
Build a rate limiter GenServer (N requests per second per user) backed by ETS.
Write a supervision tree where a Cache crashes randomly; observe restarts in :observer.
Create a chat room system using DynamicSupervisor + Registry (one process per room).
Use Task.async_stream to fetch 100 URLs concurrently with max concurrency 10 and timeouts.
Write a defenum macro that generates functions for an enum: defenum Color, [:red, :green].
Write a memoize macro that caches function results in ETS.
Connect two nodes and implement distributed ping-pong using :global names.
Build a GenStage pipeline: producer of numbers → filter stage → consumer that sums.
Build a release, run it as a daemon, attach with remote, and inspect state with :sys.get_state.