Production - Railway
Deploy long-running BullMQ worker services on Railway with the monorepo build and Railway CLI.
Connect your agent today
Draft from chat, review in your calendar, and publish only what you approve.
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 globalrailwaycommand. - 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)
| Phase | Command / setting |
|---|---|
| Build (repo root) | pnpm install && pnpm railway:orchestrator:build |
| Start — integration refresh | pnpm railway:orchestrator:start:integration-refresh |
| Start — notification email | pnpm railway:orchestrator:start:notification-email |
| Start — scheduled social post | pnpm 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.
Railpack config
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
Authenticate and link
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.
Warning
railway service to select the correct Railway service. The deploy scripts (pnpm railway:deploy:…) run railway up and will deploy to the currently linked service—if you forget to switch, you may deploy the wrong worker to the wrong service.Tip
railway link fails with Available options can not be empty, the CLI could not find any projects to link in the selected workspace.Create services and set variables (recommended once)
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.