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
.envfiles configured locally
Step 1: Create a Railway Project
- Go to railway.app and sign in with GitHub
- Click “New Project”
- Select “Deploy from GitHub repo”
- Choose your repository (e.g.,
create-ruxum-app) - 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
- In your Railway project, click ”+ New”
- Select “Database” → “PostgreSQL”
- A PostgreSQL database will be created automatically
- Copy the connection string (you’ll need it for environment variables)
Add the API Service
- Click ”+ New”
- Select “GitHub Repo” → Choose your repo again
- In the service configuration, set:
- Name:
api - Root Directory:
api - Build Command:
cargo build --release - Start Command:
./target/release/YOUR_APP_NAME
- 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
- Click ”+ New”
- Select “GitHub Repo” → Choose your repo again
- In the service configuration, set:
- Name:
web - Root Directory:
web - Build Command:
npm run build - Start Command:
npm run start
- Name:
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:
- API domain is public: Click the API service → “Settings” → Enable “Public URL” if not already enabled
- Frontend can reach API: The
NEXT_PUBLIC_API_URLshould point to the public URL from step 1
Step 5: Deploy
Once all services are configured:
- Click “Deploy” on any service, or
- 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
- Go to web service → “Settings”
- Scroll to “Domains”
- Click ”+ Add” → Enter your domain (e.g.,
app.example.com) - Update your domain registrar’s DNS records to point to the Railway domain
For API
- Go to API service → “Settings”
- Scroll to “Domains”
- Click ”+ Add” → Enter your API domain (e.g.,
api.example.com) - Update your frontend’s
NEXT_PUBLIC_API_URLto use this domain - 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:
- API service Root Directory is set to
api api/Cargo.tomlexists
”API calls fail from frontend”
Symptom: Frontend loads but API calls 404 or CORS error
Solution:
- Verify
NEXT_PUBLIC_API_URLpoints to the correct API domain - Ensure API service has “Public URL” enabled
- 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:
- Verify
DATABASE_URLenvironment variable is set - Ensure PostgreSQL service exists in your project
- Check migrations ran successfully in API logs
- 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:
- Increase build timeout in web service Settings (default 30 min)
- Optimize your Next.js build:
- Remove unused dependencies
- Use
next/dynamicfor 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
- Click service → “Settings”
- Scroll to “Plan”
- Select higher tier (Pay-as-you-go recommended for starting out)
Database Backups
- Click PostgreSQL service → “Backups”
- Enable automatic backups (Railway does this by default)
- 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
--releaseoptimizations only for final deployments
Next Steps
- Your First Endpoint — Build your API
- Your First Component — Build your frontend
- Full-Stack Integration — Connect API and frontend
- Railway Docs — Advanced Railway features