Deploy Medusa JS to Railway: A Complete Step-by-Step Guide
[Published On May 18, 2025]

When it comes to deploying your Medusa backend, you’ve got plenty of options. The main requirement is that your hosting provider supports Node.js, since that’s what Medusa runs on. For this example, we’ll be using Railway, but the same general steps apply if you’re deploying to platforms like DigitalOcean, AWS, Heroku, or others.
What You’ll Need to Deploy
Once you're ready to take your Medusa project live, there are a few key pieces you'll need to deploy:
- PostgreSQL Database
- Redis Database
- Medusa Application (in Server and Worker mode)

Medusa Admin and Application Configurations
You’ll need to deploy two instances of your Medusa application: one in server mode, and the other in worker mode.
- The "Server" instance is responsible for handling all incoming requests like API calls from your storefront, admin dashboard, or any integrations.
- The "Worker" instance runs in the background, managing tasks like scheduled jobs, event subscribers, and other long-running processes.
To get your Medusa app ready for deployment, update your medusa config (medusa-config.ts) file to support both server mode and worker mode, and to optionally disable the admin dashboard.
Here’s what you're going to add:
1module.exports = defineConfig({
2 projectConfig: {
3 // other config options...
4 workerMode: process.env.MEDUSA_WORKER_MODE as "shared" | "worker" | "server",
5 },
6 admin: {
7 disable: process.env.DISABLE_MEDUSA_ADMIN === "true",
8 backendUrl: process.env.MEDUSA_BACKEND_URL,
9 },
10})
11
You’ll set different values for MEDUSA_WORKER_MODE and DISABLE_MEDUSA_ADMIN based on which Medusa instance you’re deploying. MEDUSA_BACKEND_URL defines the backend URL your admin dashboard will connect to. We’ll generate this when we deploy to Railway.
Add the variables (MEDUSA_WORKER_MODE, DISABLE_MEDUSA_ADMIN, & MEDUSA_BACKEND_URL) to your .env file so you can easily copy and paste the values when setting up each instance.
Configure Redis URL
We’ll use the REDIS_URL environment variable to connect Medusa to Redis. We’ll set up Redis on Railway a bit later.
In your medusa-config.ts file, add the following line inside projectConfig:
1module.exports = defineConfig({
2 projectConfig: {
3 // other config options...
4 redisUrl : process.env.REDIS_URL
5 },
6})
7
Then, in your .env file, add a placeholder for the Redis connection string REDIS_URL=
We’ll come back and fill this in once Redis is deployed.
Add a Predeploy Script
To make sure your Medusa app always runs migrations and syncs links before deployment, add the following predeploy script to your package.json:
1{
2 // ...other configurations
3 "scripts": {
4 // ...other scripts
5 "predeploy": "medusa db:migrate"
6 }
7}
Configure Production Modules and Providers
For production environments, it’s highly recommended to use the Redis-based modules for caching, the event bus, and the workflow engine, rather than relying on the default in-memory versions.
In a production environment, you’ll also want to set up the S3 File Module Provider for file storage. But to keep things simple, we’ll leave it as-is for this tutorial.
Add the following Redis modules to your medusa-config.ts file:
1module.exports = defineConfig({
2 // other configurations....
3 modules: [
4 {
5 resolve: "@medusajs/medusa/cache-redis",
6 options: {
7 redisUrl: process.env.REDIS_URL,
8 },
9 },
10 {
11 resolve: "@medusajs/medusa/event-bus-redis",
12 options: {
13 redisUrl: process.env.REDIS_URL,
14 },
15 },
16 {
17 resolve: "@medusajs/medusa/workflow-engine-redis",
18 options: {
19 redis: {
20 url: process.env.REDIS_URL,
21 },
22 },
23 },
24 ],
25});
Create a GitHub Repository
Create a GitHub repository for your Medusa application — this will make things much easier when we deploy to Railway. Plus, it will also allow you to automatically deploy when changes are made to your repo. New to Github? Follow this guide.
Create a Railway Account
If you’ve made it this far, nice work! You’re now ready to deploy your Medusa app to Railway.
Go to https://railway.com/new, and create an account if you haven’t already. Make sure to connect your GitHub to your Railway account.
Create a new Railway project for your Medusa application.
Deploy PostgreSQL and Redis on Railway
In your Railway dashboard, click the “Create” button and deploy both services:
- Search for "PostgreSQL" and deploy it to set up your Medusa DB
- Search for "Redis" and deploy it as well
Make sure both are added to the same project — this allows you to use Railway's template syntax and dynamic environment variables for easy service connections.
Deploy Medusa Application in Server Mode
In your Railway project, click “Create” and select the GitHub Repo option. Choose the repository you just created for your Medusa app. Name this service “Server”, this helps keep things clear when you deploy the "Worker" instance later on.
Make sure you’re deploying this to the same Railway project where your Redis and PostgreSQL services are running — this allows you to use dynamic environment variables to connect the services.
Head back to your local Medusa project, open your .env file, and copy the relevant environment variables.
In your "Server" instance, go to the "Variables" tab and use the "Raw Editor" to paste them. Before updating, make the following additions:
1DISABLE_MEDUSA_ADMIN="false"
2MEDUSA_WORKER_MODE="server"
3PORT="9000"
4MEDUSA_BACKEND_URL=https://<your-generated-url>
5DATABASE_URL="${{ Postgres.DATABASE_PUBLIC_URL }}"
6REDIS_URL="${{ Redis.REDIS_PUBLIC_URL }}"
In your "Server" instance, go to the Settings tab, and under "Networking", click the "Generate Domain" button for your Medusa backend URL. Add this url as MEDUSA_BACKEND_URL in your variables.
1DISABLE_MEDUSA_ADMIN="false"
2MEDUSA_WORKER_MODE="server"
3PORT="9000"
4MEDUSA_BACKEND_URL=https://<your-generated-url>
5DATABASE_URL="${{ Postgres.DATABASE_PUBLIC_URL }}"
6REDIS_URL="${{ Redis.REDIS_PUBLIC_URL }}"
Also in the "Settings" tab, add the following configuration for "Custom Start Command":
cd .medusa/server && npm install && npm run predeploy && npm run start
Deploy Medusa Application in Worker Mode
Repeat the steps in "Deploy Medusa Application in Server Mode", with a couple key differences.
In your "Worker" instance on Railway, go to the Settings tab, scroll down to the "Custom Start Command" field, and add:
cd .medusa/server && npm install && npm run start
Go back to your local Medusa application, open the .env file, and copy the relevant environment variables.
Then, in your "Worker" instance, go to the "Variables" tab, click on "Raw Editor", and paste the variables. Before updating, make the following adjustments:
1DISABLE_MEDUSA_ADMIN="true"
2MEDUSA_WORKER_MODE="worker"
3PORT="9000"
4MEDUSA_BACKEND_URL=https://<your-generated-url>
5DATABASE_URL="${{ Postgres.DATABASE_PUBLIC_URL }}"
6REDIS_URL="${{ Redis.REDIS_PUBLIC_URL }}"
Connect to Railway CLI from Terminal
Once your deployment is live, you can connect to your project using the Railway CLI. It lets you run scripts, execute migrations, and manage your Medusa app directly from your terminal.
First, install the Railway CLI tool. In my case, I’ll use Homebrew to do this. (CLI installation instructions: https://docs.railway.com/guides/cli)
1brew install railway
After installing the CLI, log in to Railway:
1railway login
Once you're logged in, link your local Medusa project to your Railway project:
1railway link
When prompted to choose a project during linking, select the server instance.
To create an admin user, run the following command from your project’s root directory.
1railway run npx medusa user -e admin-medusa@test.com -p supersecret
Be sure to replace admin-medusa@test.com and supersecret with the email and password you'd like to use for your admin account.
If you’d like to seed your project with auto-generated store, products, inventory, and more, run the following command.
1railway run npx medusa exec ./src/scripts/seed.ts