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 /. This is Motia's default behavior as well. Check the configuration if Railway's healthcheck fails.
Configure Redis
Create a production config.yaml with Redis adapters for all modules. Railway auto-injects REDIS_URL when you link the Redis service to your app:
The ${REDIS_URL:redis://localhost:6379} syntax uses environment variable interpolation with a default value. Railway auto-provisions this variable when you add a Redis database.
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.
Healthcheck Failed
Cause: Railway expects a 200 response on your healthcheck path.
Options:
- Remove healthcheck settings from
railway.json - The iii runtime 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.