Trigger.dev's cloud is the easiest starting point, but for teams with strict data residency requirements or high job volumes, self-hosting gives you full control. The Trigger.dev server is open-source and ships as a Docker image. Railway is an ideal host: it handles persistent volumes, environment variables, and service networking without requiring Kubernetes or manual infrastructure management.

This guide walks through a complete self-hosted Trigger.dev setup on Railway, including the Postgres database, Redis queue, and the Trigger server itself.

Architecture Overview

Service Purpose Railway Template
trigger-server The Trigger.dev API + dashboard Custom Docker image
postgres Job metadata, run history Railway Postgres plugin
redis Job queue and pub/sub Railway Redis plugin

Step 1: Create a Railway Project

# Install Railway CLI npm install -g @railway/cli # Login and create a project railway login railway init --name trigger-self-hosted

Step 2: Add Postgres and Redis

In the Railway dashboard, click Add Service → Database → PostgreSQL, then repeat for Redis. Railway automatically sets `DATABASE_URL` and `REDIS_URL` environment variables that other services in the project can reference.

Step 3: Deploy the Trigger.dev Server

Create a `railway.toml` and `Dockerfile` for the Trigger server service:

# Dockerfile FROM ghcr.io/triggerdotdev/trigger.dev:latest # Trigger.dev reads all config from environment variables # No additional build steps needed

# railway.toml [build] dockerfilePath = "Dockerfile" [deploy] startCommand = "" healthcheckPath = "/api/v1/health" healthcheckTimeout = 300 restartPolicyType = "on_failure" restartPolicyMaxRetries = 3

Step 4: Set Environment Variables

# Required variables for the Trigger.dev server # Set these in Railway dashboard → Service → Variables DATABASE_URL=${{Postgres.DATABASE_URL}} REDIS_URL=${{Redis.REDIS_URL}} # Generate a secure random string (32+ chars) SESSION_SECRET=your-long-random-session-secret-here MAGIC_LINK_SECRET=your-long-random-magic-link-secret-here ENCRYPTION_KEY=your-32-char-hex-encryption-key # The public URL Railway assigns your service LOGIN_ORIGIN=https://trigger-server-production.up.railway.app APP_ORIGIN=https://trigger-server-production.up.railway.app # Email (required for magic link auth) RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxx FROM_EMAIL=noreply@yourapp.com REPLY_TO_EMAIL=support@yourapp.com

# Generate secrets with Node.js node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Step 5: Run Database Migrations

Trigger.dev uses Prisma for database migrations. You need to run them once after the Postgres database is ready:

# SSH into the Railway service or use railway run railway run --service trigger-server npx prisma migrate deploy

Railway's service-to-service networking uses internal hostnames. If the migration command can't reach Postgres, check that `DATABASE_URL` uses the internal Railway URL (not the public one) for security and lower latency.

Step 6: Configure Your App to Use Self-Hosted Trigger

// trigger/index.ts export const client = new TriggerClient({ id: "my-app", apiKey: process.env.TRIGGER_API_KEY!, // Point to your self-hosted instance instead of Trigger's cloud apiUrl: process.env.TRIGGER_API_URL!, // https://trigger-server-production.up.railway.app });

# .env.local (your Next.js app) TRIGGER_API_KEY=tr_dev_xxxxxxxxxxxxxxxxxxxx # created in your self-hosted dashboard TRIGGER_API_URL=https://trigger-server-production.up.railway.app

Production Checklist

Item Status Notes
Postgres backups Enable in Railway Railway offers point-in-time recovery on paid plans
Redis persistence AOF enabled by default Check Railway Redis config
HTTPS Automatic Railway provisions TLS for all public domains
Horizontal scaling Not needed Trigger server is single-instance; scale your workers instead
Worker scaling Scale your app service Multiple replicas of your Next.js/Node worker all connect to the same Trigger server
Monitoring Add Railway metrics Alert on Postgres connection count and Redis memory usage
Job history retention Configure in Trigger dashboard Default is 30 days; adjust for compliance needs

Viewing the Dashboard

Navigate to your Trigger server's Railway URL (e.g., `https://trigger-server-production.up.railway.app`). Create an account using a magic link (sent to the email you configured), then create an organization and project to get your API key.

The self-hosted Trigger dashboard is currently single-tenant (one organization per server). If you need multiple isolated organizations, deploy separate Trigger server instances.

Cost Estimate on Railway

Service Railway Cost
Trigger server (1 vCPU, 512MB) ~$5/month
Postgres (1GB storage) ~$5/month
Redis (256MB) ~$3/month
Total ~$13/month vs Trigger.dev cloud (usage-based)