← Blog

Desplegar Phoenix cuando tu cola de jobs ya vive dentro del release

Railyard

14 de octubre de 2026 · 2 min de lectura

La mayoría de los frameworks necesitan un segundo proceso desplegable solo para correr jobs en segundo plano — un dyno worker, un contenedor aparte, algo que mantener sincronizado con el build de la app web. Phoenix normalmente no, porque Oban corre como parte del mismo árbol de supervisión OTP que el propio endpoint web: el runner de jobs no es una segunda app, ya está vivo desde el momento en que web arranca.

Qué se lee desde mix.exs

  • Las bases de datos se detectan a partir de las dependencias, no se declaran dos veces: ecto_sql/postgrex aprovisiona Postgres, ecto_ch/ch aprovisiona ClickHouse, redix aprovisiona Redis.
  • SECRET_KEY_BASE se genera una sola vez, no te lo deja a ti para producirlo y guardarlo tú mismo.
  • MIX_ENV=prod y PHX_SERVER=true se definen automáticamente — los dos flags de entorno que un release compilado de Phoenix de verdad necesita para servir tráfico en vez de quedarse inactivo.
railyard create my-app https://github.com/me/my-app --addons postgres

o la misma URL de Git desde el panel una vez que GitHub está conectado.

La parte genuinamente distinta de los releases compilados

Un release compilado de Elixir no tiene mix en tiempo de ejecución — el comando de migración que funciona en desarrollo (mix ecto.migrate) no existe en el artefacto que de verdad se despliega. Railyard encuentra dondequiera que el release ponga su propio migrador y corre eso en su lugar (bin/migrate si el release define uno, de lo contrario bin/<app> eval), y mix phx.server se convierte en bin/<app> start de la misma forma. Esa distinción — comando de desarrollo versus lo que el release compilado realmente expone — es lo que más comúnmente hace tropezar un primer despliegue de Elixir en cualquier plataforma, y aquí se maneja antes de que corra la primera migración.

Si de verdad vale la pena un nodo worker dedicado

Oban no necesita un segundo proceso para la mayoría de las apps — pero si el volumen de jobs es lo bastante alto como para que una cola lenta empiece a competir por recursos con los requests web, separarlo en su propio nodo sigue siendo una línea más, no un cambio de arquitectura:

web:    bin/my_app start
worker: bin/my_app eval "MyApp.Release.worker()"
railyard scale my-app worker=2

El mismo release, el mismo build, iniciado de forma distinta — agrégalo o edítalo desde la pestaña Workers sin necesidad de ningún cambio en el repo.

Configuración y secretos

Todo lo que config/runtime.exs lee con System.get_env/2 — BASE_URL, HTTP_PORT, LISTEN_IP, DATABASE_URL, CLICKHOUSE_DATABASE_URL y cualquier otra cosa — es una variable simple en Variables, o se define vía railyard env:set my-app KEY=VALUE, nunca horneada en el release compilado. El mismo release corre sin cambios desde staging hasta producción.

Referencia completa: Documentación de Phoenix y Elixir, Workers y jobs programados.

Despliega una app de Phoenix ahora mismo.

mix.exs se lee automáticamente — ecto.migrate, SECRET_KEY_BASE y la base de datos quedan todos conectados.

Plan gratis, sin tarjeta, y 14 días de Pro para cada equipo nuevo. Un precio fijo por equipo.