Deploy to Railway
Deploy your Motia app to Railway with Redis for production-grade backends
Railway makes deploying Motia apps dead simple. Connect your repo, add Redis, and you're live in minutes.
This guide walks you through deploying a production-ready Motia app with real Redis (not in-memory) on Railway.
What you'll get: A fully containerized Motia app running on Railway with external Redis for state, events, streams, and cron locking.
Example Project: Follow along with the Todo App example - a complete deployment-ready Motia app with Redis configuration.
Prerequisites
Before you start:
- A Railway account (free tier works)
- Railway CLI installed
- Docker running locally (for testing)
- A Motia project ready to deploy
Install the Railway CLI:
Quick Start
Initialize your project
From your Motia project root:
This creates a new Railway project with the specified name.
Project Setup
Docker Files
If you haven't already, generate the Docker files:
This creates Dockerfile and .dockerignore in your project.
Update Your Start Script
Railway injects the port via the PORT environment variable. Update your package.json:
This ensures Motia listens on the port Railway expects.
Railway Configuration
Create a railway.json in your project root:
Healthchecks: Railway's default healthcheck expects a 200 response on /. Motia's Workbench serves the root path, so this should work out of the box.
Configure Redis
Motia supports two approaches for production Redis configuration:
Option 1: Simple Redis Config (Recommended)
The simplest approach uses Motia's built-in redis configuration option:
That's it! Motia handles the Redis adapters automatically when you use the redis config option. Railway auto-injects REDIS_URL when you link the Redis service to your app.
Option 2: Custom Adapters (Advanced)
For more control over individual adapters, you can configure them manually:
Set Environment Variables
Railway auto-provisions Redis variables when you add the Redis database. Link them to your app:
Set the variables
The ${{Redis.REDIS_URL}} syntax tells Railway to inject the actual Redis URL at runtime.
Internal vs Public URL: Railway provides both internal (redis.railway.internal) and public proxy URLs for Redis. Use REDIS_PRIVATE_URL for faster internal connections. If you have connection issues, try the public URL from your Redis service's settings.
Deploy and Test
Deploy Your App
Watch the build logs. Once complete, Railway deploys your container.
Get Your Domain
Railway assigns a public URL like https://your-app-production-xxxx.up.railway.app.
Test Your API
If you get a JSON response with your data, you're running on production Redis!
View Logs
Check what's happening in your deployed app:
Add --tail to stream logs in real-time:
Troubleshooting
502 Application Failed to Respond
Cause: Usually means the app isn't listening on the right port.
Fix: Make sure your start script uses ${PORT:-3000}:
Redis Connection Errors
Cause: The app can't reach Redis.
Check:
- Is the Redis service running? Check Railway dashboard.
- Is
REDIS_URLset correctly? Runrailway variablesto verify. - Try the public Redis URL if internal isn't working.
Plugin Not Loading
Cause: Plugin imports might not be resolving correctly.
Fix: Use ESM imports (recommended for "type": "module" projects):
Healthcheck Failed
Cause: Railway expects a 200 response on your healthcheck path.
Options:
- Remove healthcheck settings from
railway.json - Motia Workbench serves
/by default which returns 200 - Increase the healthcheck timeout
Still Seeing "Redis Memory Server Started"
Cause: The app is falling back to in-memory Redis.
Check:
- Is
NODE_ENV=productionorUSE_REDIS=trueset? - Is
REDIS_URLresolving correctly? - Check logs for Redis connection errors.
Scaling
Need more instances? Update your railway.json:
With Redis configured, all instances share state, events, and streams. Requests get load-balanced automatically.
What's Next?
Deploy to Fly.io
Alternative cloud platform with global edge deployment
Self-Hosted
Full control with your own infrastructure