Logo

Bridger Tower / Designer and Software Engineer

Deploying Mastra to Railway

A step by step guide to deploying Mastra to Railway.

This guide will walk you through deploying your Mastra application to Railway, a modern deployment platform that makes it easy to deploy Node.js applications.

Prerequisites

Before starting, ensure you have:

  • A Mastra.ai project set up locally
  • Node.js 18.x or later installed
  • A Railway account (sign up with GitHub for easier integration)
  • A GitHub account (for GitHub deployment method)
  • Railway CLI installed (for CLI deployment method)

Understanding Mastra Deployment

Mastra uses Hono as its underlying HTTP server framework. When you build a Mastra application using mastra build, it generates a production-ready Hono-based HTTP server in the .mastra/output directory. This makes it compatible with any Node.js hosting platform, including Railway.

Key Points:

  • Development server (mastra dev) runs on port 3000
  • Production server defaults to port 4111 (configurable)
  • Build output is generated in .mastra/output/
  • The built server is a standard Node.js application

Step 1: Prepare Your Mastra Application

1.1 Configure Your Mastra Instance

First, ensure your Mastra instance is properly configured for production. In your main Mastra configuration file (typically src/mastra/index.ts):

typescript
1import { Mastra } from "@mastra/core";
2
3export const mastra = new Mastra({
4 // Configure server settings
5 server: {
6 port: process.env.PORT || 4111, // Railway sets PORT automatically
7 timeout: 30000, // 30 seconds
8 },
9 // Add your agents, workflows, and other configurations
10 agents: {
11 // your agents here
12 },
13 // Add any logging configuration
14 logger: {
15 level: process.env.NODE_ENV === "production" ? "info" : "debug",
16 },
17});

1.2 Update package.json

Ensure your package.json includes the necessary scripts and Node.js version:

json
1{
2 "name": "your-mastra-app",
3 "version": "1.0.0",
4 "engines": {
5 "node": ">=18.0.0"
6 },
7 "scripts": {
8 "dev": "mastra dev",
9 "build": "mastra build",
10 "start": "node .mastra/output/index.js",
11 "postinstall": "mastra build"
12 },
13 "dependencies": {
14 "@mastra/core": "latest"
15 // your other dependencies
16 },
17 "devDependencies": {
18 "mastra": "latest",
19 "typescript": "^5.0.0",
20 "@types/node": "^18.0.0"
21 }
22}

Important Notes:

  • The postinstall script ensures Mastra builds automatically after Railway installs dependencies
  • The start script runs the built Hono server from .mastra/output/index.js
  • mastra CLI is a devDependency, while @mastra/core is a regular dependency

1.3 Environment Variables

Create a .env.example file to document required environment variables:

bash
1# LLM API Keys
2OPENAI_API_KEY=your_openai_key
3ANTHROPIC_API_KEY=your_anthropic_key
4GOOGLE_GENERATIVE_AI_API_KEY=your_gemini_key
5
6# Database (if using)
7DATABASE_URL=your_database_url
8
9# Other configuration
10NODE_ENV=production

Note: Never commit your actual .env file to Git. Add it to .gitignore.

1.4 Update .gitignore

Ensure your .gitignore includes:

# Environment variables .env .env.local # Mastra build output .mastra/ # Node modules node_modules/ # TypeScript build info *.tsbuildinfo

Step 2: Build Your Application Locally

Before deploying, test the production build locally:

bash
1# Build the application
2npm run build
3
4# This creates the production server in .mastra/output/
5
6# Test the production server
7NODE_ENV=production npm start
8# Or run directly:
9NODE_ENV=production node .mastra/output/index.js

This should start your Mastra server on the configured port (default 4111).

Step 3: Deploy to Railway

You have three options for deploying to Railway:

Option A: Deploy from GitHub (Recommended)

  1. Push your code to GitHub:

    bash
    1git add .
    2git commit -m "Prepare for Railway deployment"
    3git push origin main
  2. Create a new Railway project:

    • Go to Railway Dashboard
    • Click "New Project"
    • Select "Deploy from GitHub repo"
    • Authorize Railway to access your GitHub (if not already done)
    • Select your Mastra repository
    • Choose the branch to deploy (usually main)
  3. Configure environment variables:

    • In the Railway project dashboard, click on your service
    • Go to the "Variables" tab
    • Click "Add Variable" and add all your environment variables:
      • OPENAI_API_KEY
      • ANTHROPIC_API_KEY
      • DATABASE_URL (if applicable)
      • Any other required variables
  4. Deploy:

    • Railway will automatically detect it's a Node.js app
    • It will run npm install followed by npm run build (via postinstall)
    • Then it will run npm start to start your server

Option B: Deploy with Railway CLI

  1. Install Railway CLI:

    bash
    1npm install -g @railway/cli
  2. Login to Railway:

    bash
    1railway login
  3. Initialize a new project:

    bash
    1railway init

    Follow the prompts to name your project.

  4. Set environment variables:

    bash
    1railway variables set OPENAI_API_KEY=your_key
    2railway variables set ANTHROPIC_API_KEY=your_key
    3# Set other variables as needed
  5. Deploy:

    bash
    1railway up

Option C: Deploy with Dockerfile

If you prefer more control, create a Dockerfile:

dockerfile
1# Use Node.js LTS
2FROM node:18-alpine
3
4# Set working directory
5WORKDIR /app
6
7# Copy package files
8COPY package*.json ./
9
10# Install dependencies (including devDependencies for build)
11RUN npm ci
12
13# Copy application files
14COPY . .
15
16# Build Mastra application
17RUN npm run build
18
19# Remove devDependencies after build
20RUN npm prune --production
21
22# Expose port (Railway sets PORT automatically)
23EXPOSE 4111
24
25# Start the application
26CMD ["node", ".mastra/output/index.js"]

Then deploy using either GitHub or CLI method above.

Step 4: Generate a Public Domain

Once deployment is complete:

  1. In your Railway project dashboard, click on your service
  2. Go to the "Settings" tab
  3. Under "Networking", click "Generate Domain"
  4. Railway will provide a URL like your-app.up.railway.app

Step 5: Configure Client Applications

Update your client applications to use the Railway URL:

typescript
1import { MastraClient } from "@mastra/client-js";
2
3const client = new MastraClient({
4 baseUrl:
5 process.env.NODE_ENV === "production"
6 ? "https://your-app.up.railway.app"
7 : "http://localhost:4111",
8});

Deployment Best Practices

1. Use Environment-Specific Configuration

typescript
1const isDevelopment = process.env.NODE_ENV !== "production";
2
3export const mastra = new Mastra({
4 server: {
5 port: process.env.PORT || 4111,
6 cors: {
7 origin: isDevelopment
8 ? ["http://localhost:3000"]
9 : ["https://your-frontend.com"],
10 },
11 },
12});

2. Set Up Health Checks

Add a health check endpoint to monitor your application:

typescript
1mastra.route({
2 method: "GET",
3 path: "/health",
4 handler: async (req) => {
5 return new Response(
6 JSON.stringify({
7 status: "healthy",
8 timestamp: new Date().toISOString(),
9 }),
10 {
11 headers: { "Content-Type": "application/json" },
12 }
13 );
14 },
15});

3. Configure Logging

Use appropriate logging levels for production:

typescript
1import { PinoLogger } from "@mastra/loggers";
2
3export const mastra = new Mastra({
4 logger: new PinoLogger({
5 name: "mastra-app",
6 level: process.env.LOG_LEVEL || "info",
7 }),
8});

4. Database Considerations

If using a database with Mastra:

  • Railway provides PostgreSQL databases that work well with Mastra
  • The DATABASE_URL will be automatically set when you provision a database
  • Important: Railway uses an ephemeral file system, so avoid file-based storage
  • For SQLite/LibSQL, use remote URLs instead of file-based storage (e.g., Turso)
  • Never use file:./database.db or similar file paths on Railway

Monitoring and Debugging

View Logs

In Railway dashboard:

  1. Click on your service
  2. Go to the "Logs" tab to see real-time logs
  3. Use filters to search for specific log entries

Using Railway CLI for logs:

bash
1railway logs

Check Deployment Status

Monitor your deployment:

  • Build logs show compilation and dependency installation
  • Deploy logs show the running application
  • Look for "Server running on port XXXX" or similar message to confirm successful start
  • The built Hono server will log when it's ready to accept connections

Common Issues and Solutions

Issue: Build fails with "mastra: command not found"

Solution: Ensure mastra is in your devDependencies:

json
1{
2 "devDependencies": {
3 "mastra": "latest"
4 }
5}

Issue: Server starts but can't be accessed

Solution: Ensure your server binds to 0.0.0.0 and uses Railway's PORT:

typescript
1server: {
2 port: process.env.PORT || 4111,
3 hostname: '0.0.0.0'
4}

Issue: Environment variables not working

Solution:

  • Check Railway's Variables tab for typos
  • Restart the service after adding variables
  • Use railway variables CLI command to verify

Issue: Memory or timeout errors

Solution: Railway's free tier has limits. For production:

  • Upgrade to a paid plan for more resources
  • Optimize your Mastra workflows
  • Implement proper error handling and timeouts

Next Steps

  1. Set up CI/CD: Railway automatically deploys on push to your connected branch
  2. Configure custom domain: Add your own domain in Railway's settings
  3. Set up monitoring: Use Railway's metrics or integrate external monitoring
  4. Scale your application: Railway supports both vertical and horizontal scaling

Additional Resources

Conclusion

Deploying Mastra.ai to Railway is straightforward since Mastra builds to a standard Node.js server. Railway's automatic detection of Node.js applications and simple deployment process make it an excellent choice for hosting Mastra applications. Remember to properly configure environment variables, monitor your application logs, and follow production best practices for optimal performance.

© Bridger Tower, 2025