Railway Deployment
Railway provides a simple platform for deploying Rivet Engine with automatic scaling and managed infrastructure.
Video Tutorial
PostgreSQL is the recommended backend for multi-node self-hosted deployments today, but it remains experimental. For a production-ready single-node Rivet deployment, use the file system backend (RocksDB-based). Enterprise teams can contact enterprise support about FoundationDB for the most scalable production-ready deployment.
Quick Deploy
Choose the template that best fits your needs:
You can also use the Rivet Railway template as a starting point for your application.
After deploying either template, you can find the RIVET__AUTH__ADMIN_TOKEN under the Variables tab in the Railway dashboard. This token is required to access the Rivet Inspector.
Manual Deployment
Prerequisites
- Railway account
- Railway CLI (optional)
Step 1: Create New Project
# Using Railway CLI
railway init
# Or create via dashboard
# https://railway.app/new
Step 2: Add Services
Deploy PostgreSQL Database
- Click “New Service” → “Database” → “PostgreSQL”
- Railway automatically provisions and configures PostgreSQL
- Note the connection string from the service variables
Deploy Rivet Engine
- Click “New Service” → “Docker Image”
- Set image:
rivetdev/engine:latest - Configure environment variables:
RIVET__POSTGRES__URL=${{Postgres.DATABASE_URL}}
- Configure graceful shutdown (see Graceful Shutdown below)
Step 3: Deploy Your Application
Follow the Railway Quick Start guide to deploy your repository:
- Connect your GitHub account to Railway
- Select your repository containing your Rivet application
- Railway will automatically detect and deploy your application
- Configure environment variables for your application:
RIVET_ENDPOINT=${{Rivet.RAILWAY_PRIVATE_DOMAIN}}- Points to the Rivet Engine service’s private domain
WebSocket Timeouts
Rivet uses long-lived WebSocket connections for both client traffic (browsers, SDKs) and envoy traffic (actor hosts connecting back to the engine). Railway’s HTTP proxy supports WebSockets, but you must make sure no app-side timeout cuts them off.
If you front the engine with your own reverse proxy (NGINX, Caddy, etc.) inside the Railway service, raise its idle / read timeout to at least 1 hour (3600 seconds). The same guidance applies to the Railway service hosting your RivetKit app, since envoys connect to it over WebSocket.
Graceful Shutdown
By default, Railway kills the old deploy 0 seconds after sending SIGTERM (see Railway’s docs), so in-flight requests are dropped and state flushes can be interrupted on every deploy. Rivet ships with a SIGTERM handler that drains cleanly, but it only gets to run if Railway is configured to give it time.
Configure the following under Settings → Deploy on your service:
- Draining seconds — the grace window between
SIGTERMandSIGKILL. This is how long Rivet has to finish in-flight work and flush state. See Railway’s deployment teardown docs.
Set draining seconds in the dashboard, via drainingSeconds in config-as-code, or via the RAILWAY_DEPLOYMENT_DRAINING_SECONDS service variable. A reasonable value is 60 seconds.
If your start command is a wrapper process (for example npm start, yarn start, pnpm start, or a shell script), the wrapper becomes PID 1 and swallows the signal — your app never drains and Railway force-kills it at the end of the window.
- Invoke your binary directly as the start command (for example
node dist/index.js, notnpm start). - Or run
dumb-init/tinias PID 1 in your Dockerfile so signals forward to your process.
Next Steps
- Review the Production Checklist before going live
- See Configuration for all options