Skip to content

Production - Railway

Deploy long-running BullMQ worker services on Railway with the monorepo build and Railway CLI.

5 min read

Connect your agent today

Draft from chat, review in your calendar, and publish only what you approve.

Start for $0

This guide covers orchestrator worker deployments on Railway: always-on processes that consume BullMQ queues while your API may live on Vercel.

Railway treats these as persistent services (containers that keep running). See also Configuration - Worker for env vars and Orchestrator workflows for when to use bullmq transport.

Prerequisites

  • Railway account and Railway CLI on your PATH. This guide uses the global railway command.
  • Worker environment variables set on each Railway service (applies to dashboard deploys and CLI deploys):
    • REDIS_* (shared with your API). See Redis cache.
    • Supabase keys — PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_PUBLISHABLE_KEY, and SUPABASE_SECRET_KEY. Legacy JWT keys are not accepted; see Supabase and Configuration - Worker.
    • Storage public URL for media publishing (recommended if you schedule posts with images/videos): STORAGE_PROVIDER and STORAGE_R2_PUBLIC_BASE_URL (no trailing slash). See R2 or local storage.
    • RAILPACK_CONFIG_FILE set per worker service (see “Set variables per worker service” below).

Build and start (summary)

PhaseCommand / setting
Build (repo root)pnpm install && pnpm railway:orchestrator:build
Start — integration refreshpnpm railway:orchestrator:start:integration-refresh
Start — notification emailpnpm railway:orchestrator:start:notification-email
Start — scheduled social postpnpm railway:orchestrator:start:scheduled-social-post

The repo includes railway.toml at the monorepo root with buildCommand, a restart policy, region us-west2 (US West / Oregon), and replica limits for the lighter workers (numReplicas = 1, 1 vCPU, 1 GiB). scheduled-social-post uses railway.scheduled-social-post.toml (1 vCPU, 2 GiB) — set that service’s Railway Config File to /railway.scheduled-social-post.toml. Start command is not fixed in those files so each worker can differ (config as code).

Dashboard setup

Create project resources

Add Redis (and reference its connection into worker variables as REDIS_*). Add one Railway service per worker you need (integration refresh, notification email, and/or scheduled social posts), or split later—each needs its own Start Command; set RAILPACK_CONFIG_FILE to the railpack file for that worker at the repo root (see the callout below).

Name the services after the worker they run (recommended), but the exact service names are up to you. The CLI bootstrap uses the linked service (see “Railway CLI” below).

Connect the GitHub repo

Use the same repository as the monorepo. Configure monorepo settings so install/build run from the repository root.

Set variables per worker service

Set NODE_ENV=production, Redis, Supabase, and any provider/email keys from Configuration - Worker.

Set Start Command

In the service Settings → Deploy → Start Command, set exactly one of the following (from the monorepo root).

Integration refresh worker

pnpm railway:orchestrator:start:integration-refresh

Notification email worker

pnpm railway:orchestrator:start:notification-email

Scheduled social post worker (calendar publishes at publish_date) —

pnpm railway:orchestrator:start:scheduled-social-post

Avoid scale-to-zero if it would stop a process during long integration-refresh sleeps.

Railway CLI

Prerequisite: install the Railway CLI

Install the CLI so the railway command is available globally (or on your PATH). Follow Installing the Railway CLI — for example:

npm i -g @railway/cli

You can also deploy each worker with the Railway CLI instead of (or in addition to) GitHub-triggered deploys from the dashboard. To avoid deploying the wrong worker, prefer the repo scripts that set the correct Railpack config for you:

  • pnpm railway:setup:integration-refresh (one-time: create service + set variables via CLI)
  • pnpm railway:setup:notification-email (one-time: create service + set variables via CLI)
  • pnpm railway:setup:scheduled-social-post (one-time: create service + set variables via CLI)
  • pnpm railway:deploy:integration-refresh
  • pnpm railway:deploy:notification-email
  • pnpm railway:deploy:scheduled-social-post

Deploy a worker from your machine

Choose your Railway project and the worker service. Run railway link again only if you need a fresh link.

From the repository root:

railway login
railway init
railway link
railway service

If you see No service linked, run railway service to link a service for this directory.

If this is the first time setting up a worker service, create the services and set variables via the setup scripts:

pnpm railway:setup:integration-refresh
pnpm railway:setup:notification-email
pnpm railway:setup:scheduled-social-post

These scripts create empty services (if missing) and call railway variable set with —skip-deploys so you can safely configure variables before deploying.

Deploy

For each deploy, the linked service must have RAILPACK_CONFIG_FILE set to the matching railpack file (or use the Create services and set variables setup scripts above), otherwise Railpack will report No start command detected. Switch services with railway service (or railway unlink and railway link) when moving between workers.

Integration refresh

pnpm railway:deploy:integration-refresh

Notification email

pnpm railway:deploy:notification-email

Scheduled social post

pnpm railway:deploy:scheduled-social-post

Each command ships the current directory to the currently linked service. Full CLI reference: Railway CLI.

Search documentation
Find a docs page
Discord Support