F6.08 · part 3 of 3
Deploying to production
With auth in place and a release configured, deploying is three steps in order: build
the release, migrate the database, boot the system. Building runs
mix release to produce the artifact from F6.08.2. Migrating runs the
Portal.Release command against the live database before the new code serves traffic, so
the schema is ready. Booting starts bin/portal, which evaluates
runtime.exs to read the environment and then starts the application’s
supervision tree — and this is the moment the whole course pays off. The tree is the same
one from F5: it starts the Repo, the Endpoint, PubSub, Presence, and the engine in order, and if any child
crashes it restarts under the supervisor’s strategy. You do not start processes by hand or write health
checks to revive them; the tree is the health model. The last production concern is scale: running more than one
node means clustering them so the F6.07 broadcasts and Presence reach across machines, which a
library like libcluster handles by connecting the nodes — after which the exact same broadcast code spans
the cluster. Build, migrate, boot, and the platform is live.
Four parts: the three deploy steps, the supervision tree in production, clustering for PubSub and Presence, and the deploy as a sequence of commands.
Build, migrate, boot
A deploy is three ordered steps. Build compiles the release artifact. Migrate applies pending migrations to the database. Boot starts the supervision tree so the endpoint serves. Select one.
The deploy · select a step
step: build
does: compile the release artifact
Order matters: migrate before boot, so the new code never meets an old schema. Run the migration against the live database as its own step, then start the release that expects the new shape.
The tree in production
Booting the release starts the application’s supervision tree — the same structure you designed in F5. The supervisor starts the Repo, the Endpoint, PubSub, Presence, and the engine, in order, and watches them. A crash in any child is isolated and restarted under the supervisor’s strategy, so the system self-heals without a process manager outside the BEAM. The deploy starts one thing: the tree.
one supervisor → supervised children, restarted on crash
Everything in this chapter became a child of this tree: the Endpoint from F6.01, the Repo from F6.03, PubSub and Presence from F6.07, all beside the F5 engine. Deployment is starting that tree on a server.
Clustering the nodes
One node needs no clustering; more than one does, because PubSub and Presence coordinate over the Erlang
distribution between connected nodes. A library like libcluster joins them
automatically by a strategy — here, discovering peers in a Kubernetes service. Once the nodes are
connected, a broadcast on "courses" reaches subscribers on every node with no change
to the publishing code from F6.07.
# config/runtime.exs — connect the nodes so PubSub & Presence span them config :libcluster, topologies: [ portal: [ strategy: Cluster.Strategy.Kubernetes, config: [service: "portal-headless", application_name: "portal"] ] ] # once clustered, a broadcast on "courses" reaches subscribers on every node
This is the BEAM’s distribution doing the work: clustering is a connection concern, not an application rewrite. The real-time code you wrote for one node is already the code that runs across many.
The deploy, end to end
The whole deploy is three commands in order. Build the artifact, run the migrations through the release
command, then start the system — at which point runtime.exs reads the
environment and the supervision tree comes up serving. Roll forward by repeating it with new code; roll back
by booting the previous artifact.
# the deploy, start to finish MIX_ENV=prod mix release # 1. build the self-contained artifact bin/portal eval "Portal.Release.migrate()" # 2. run migrations (no mix on the server) bin/portal start # 3. boot: runtime.exs reads env, the tree serves
three steps
Build the release, migrate the database, boot the system.
one running tree
The F5 supervision tree serves, clustered for real-time across nodes.
That completes F6.08, and with it the application is deployable: authenticated, packaged as a release, and booted as a supervised, clustered tree. The chapter closes with F6.09, which assembles the live dashboard on everything built across F5 and F6. Back to the module overview or the F6 chapter.