Railway is the easiest way to deploy both your Rust API and Next.js frontend. This guide covers the complete deployment process.

Prerequisites

  • Railway account (sign up with GitHub)
  • Git repository with your code pushed to GitHub
  • Both API and frontend code in the same monorepo
  • .env files configured locally

Step 1: Create a Railway Project

  1. Go to railway.app and sign in with GitHub
  2. Click “New Project”
  3. Select “Deploy from GitHub repo”
  4. Choose your repository (e.g., create-ruxum-app)
  5. Click “Deploy”

Railway will automatically detect your monorepo structure.

Step 2: Configure the Rust API Service

Once your repository is imported:

Create a Database Service

  1. In your Railway project, click ”+ New”
  2. Select “Database”“PostgreSQL”
  3. A PostgreSQL database will be created automatically
  4. Copy the connection string (you’ll need it for environment variables)

Add the API Service

  1. Click ”+ New”
  2. Select “GitHub Repo” → Choose your repo again
  3. In the service configuration, set:
    • Name: api
    • Root Directory: api
    • Build Command: cargo build --release
    • Start Command: ./target/release/YOUR_APP_NAME

Replace YOUR_APP_NAME with your actual binary name (from api/Cargo.toml [package] name).

Set Environment Variables for API

Click on the API service → “Variables” tab:

DATABASE_URL=postgres://user:password@postgres-host:5432/railway
RUST_LOG=info
RUST_ENV=production

Railway automatically provides DATABASE_URL from the PostgreSQL service. You can reference it with:

DATABASE_URL=${{Postgres.DATABASE_URL}}

Click the reference icon to auto-populate it.

Step 3: Configure the Next.js Frontend Service

Add the Frontend Service

  1. Click ”+ New”
  2. Select “GitHub Repo” → Choose your repo again
  3. In the service configuration, set:
    • Name: web
    • Root Directory: web
    • Build Command: npm run build
    • Start Command: npm run start

Set Environment Variables for Frontend

Click on the web service → “Variables” tab:

NEXT_PUBLIC_API_URL=https://api-YOUR_PROJECT.up.railway.app
NODE_ENV=production

Replace api-YOUR_PROJECT.up.railway.app with your actual API domain (you can find it in the API service’s “Public URLs” section after deployment).

Step 4: Connect Services

Railway automatically creates a private network between services. However, you need to ensure:

  1. API domain is public: Click the API service → “Settings” → Enable “Public URL” if not already enabled
  2. Frontend can reach API: The NEXT_PUBLIC_API_URL should point to the public URL from step 1

Step 5: Deploy

Once all services are configured:

  1. Click “Deploy” on any service, or
  2. Push a commit to your GitHub repository (Railway will auto-deploy)

Railway will:

  • Build your Rust API (cargo build --release)
  • Run database migrations (if configured)
  • Build your Next.js frontend (npm run build)
  • Start both services
  • Assign public domains

Step 6: Verify Deployment

Check API Health

Visit your API’s public URL:

https://api-YOUR_PROJECT.up.railway.app/health

Should return:

{"status": "ok"}

Check Frontend

Visit your web service’s public URL:

https://web-YOUR_PROJECT.up.railway.app

Your app should load and API calls should work.

View Logs

Click on each service → “Logs” tab to see real-time logs:

API logs: Check for Rust panics or startup errors
Web logs: Check for Next.js build or runtime errors

Step 7: Set Up Custom Domain (Optional)

For Frontend

  1. Go to web service → “Settings”
  2. Scroll to “Domains”
  3. Click ”+ Add” → Enter your domain (e.g., app.example.com)
  4. Update your domain registrar’s DNS records to point to the Railway domain

For API

  1. Go to API service → “Settings”
  2. Scroll to “Domains”
  3. Click ”+ Add” → Enter your API domain (e.g., api.example.com)
  4. Update your frontend’s NEXT_PUBLIC_API_URL to use this domain
  5. Update both services’ environment variables

Common Issues

”Build failed: cargo not found”

Solution: Make sure api folder has Cargo.toml and Railway detects it as Rust.

Check:

  1. API service Root Directory is set to api
  2. api/Cargo.toml exists

”API calls fail from frontend”

Symptom: Frontend loads but API calls 404 or CORS error

Solution:

  1. Verify NEXT_PUBLIC_API_URL points to the correct API domain
  2. Ensure API service has “Public URL” enabled
  3. Add CORS header in your Rust API:
use axum::middleware::Next;
use hyper::header::{HeaderValue, ALLOW_ORIGIN};
use http::Request;

pub async fn cors_middleware<B>(req: Request<B>, next: Next) -> impl IntoResponse {
    let mut response = next.run(req).await;
    response.headers_mut().insert(
        "Access-Control-Allow-Origin",
        HeaderValue::from_static("*"), // or your frontend domain
    );
    response
}

“Database connection refused”

Symptom: API crashes with “connection refused” error

Solution:

  1. Verify DATABASE_URL environment variable is set
  2. Ensure PostgreSQL service exists in your project
  3. Check migrations ran successfully in API logs
  4. If migrations needed, add to Build Command:
./api/migrations && cargo build --release

“Next.js build timeout”

Symptom: Deployment hangs or times out during npm run build

Solution:

  1. Increase build timeout in web service Settings (default 30 min)
  2. Optimize your Next.js build:
    • Remove unused dependencies
    • Use next/dynamic for code splitting
    • Consider disabling source maps in production

Environment Variables Reference

API (.env)

DATABASE_URL=postgres://user:password@host:5432/db
RUST_LOG=info
RUST_ENV=production
PORT=3001

Frontend (.env.local)

NEXT_PUBLIC_API_URL=https://api.example.com
NODE_ENV=production

Monitoring & Logs

View Real-Time Logs

Click any service → “Logs” tab to stream logs:

[INFO] Server listening on 0.0.0.0:3001

Set Up Alerts

Coming soon in Railway dashboard. For now, check logs regularly or use external monitoring.

Scaling

Increase Resources

  1. Click service → “Settings”
  2. Scroll to “Plan”
  3. Select higher tier (Pay-as-you-go recommended for starting out)

Database Backups

  1. Click PostgreSQL service → “Backups”
  2. Enable automatic backups (Railway does this by default)
  3. Backups are retained for 7 days

Troubleshooting

“Service stuck in deploying state”

  • Click service → “Redeploy”
  • If still stuck, restart by pushing a new commit

“Public URL not showing”

  • Wait 2-3 minutes after deployment
  • Refresh the page
  • Check “Settings”“Public URL” toggle is enabled

“Builds are slow”

  • This is normal for Rust first builds (10-20 min)
  • Subsequent builds are faster due to caching
  • Consider using --release optimizations only for final deployments

Next Steps