AgentSkillsCN

Railway Patterns

Railway模式

SKILL.md

Railway Patterns

Multi-service architecture patterns for production apps

Activation Triggers

  • Building full-stack applications
  • Microservices architecture
  • Production deployments
  • Multi-service communication
  • Complex project structures

Pattern 1: Frontend + Backend + Database

The most common full-stack pattern.

Architecture

code
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Frontend  │────▶│   Backend   │────▶│  Postgres   │
│  (Next.js)  │     │  (Express)  │     │  (Database) │
└─────────────┘     └─────────────┘     └─────────────┘
     Public              Public            Private

Deployment Sequence

code
1. check-railway-status
2. create-project-and-link
3. deploy-template "Postgres database"
4. Deploy backend:
   - link-service to backend directory
   - set-variables:
     DATABASE_URL=${{Postgres.DATABASE_URL}}
     NODE_ENV=production
   - deploy
   - generate-domain
5. Deploy frontend:
   - Create new service for frontend
   - set-variables:
     NEXT_PUBLIC_API_URL=https://${{backend.RAILWAY_PUBLIC_DOMAIN}}
   - deploy
   - generate-domain

Environment Variables

Backend:

code
NODE_ENV=production
DATABASE_URL=${{Postgres.DATABASE_URL}}
JWT_SECRET=xxx

Frontend:

code
NEXT_PUBLIC_API_URL=https://${{backend.RAILWAY_PUBLIC_DOMAIN}}

Pattern 2: API + Worker + Queue

For background job processing.

Architecture

code
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│     API     │────▶│    Redis    │◀────│   Worker    │
│  (Express)  │     │   (Queue)   │     │  (Processor)│
└─────────────┘     └─────────────┘     └─────────────┘
     Public            Private            Private

Deployment Sequence

code
1. deploy-template "Redis"
2. Deploy API:
   - set-variables:
     REDIS_URL=${{Redis.REDIS_URL}}
   - deploy
   - generate-domain
3. Deploy Worker:
   - set-variables:
     REDIS_URL=${{Redis.REDIS_URL}}
   - deploy
   - (no domain needed - internal only)

Code Pattern (Bull/BullMQ)

API (queue producer):

javascript
import { Queue } from 'bullmq';

const queue = new Queue('jobs', {
  connection: { url: process.env.REDIS_URL }
});

// Add job
await queue.add('process-data', { data: '...' });

Worker (queue consumer):

javascript
import { Worker } from 'bullmq';

const worker = new Worker('jobs', async (job) => {
  // Process job
  console.log('Processing:', job.data);
}, {
  connection: { url: process.env.REDIS_URL }
});

Pattern 3: Microservices

Multiple services communicating internally.

Architecture

code
┌─────────────┐
│   Gateway   │
│   (Public)  │
└──────┬──────┘
       │
   ┌───┴───┐
   ▼       ▼
┌──────┐ ┌──────┐
│Users │ │Orders│
│ API  │ │ API  │
└──────┘ └──────┘
Private   Private
   │         │
   ▼         ▼
┌──────┐ ┌──────┐
│UserDB│ │Order │
│      │ │  DB  │
└──────┘ └──────┘

Private Networking

Use RAILWAY_PRIVATE_DOMAIN for internal communication:

code
# Gateway environment:
USERS_API=http://${{users-api.RAILWAY_PRIVATE_DOMAIN}}:3001
ORDERS_API=http://${{orders-api.RAILWAY_PRIVATE_DOMAIN}}:3002

Benefits

  • No egress costs for internal traffic
  • Lower latency
  • Services not exposed publicly

Pattern 4: Monorepo Deployment

Single repo with multiple apps.

Structure

code
my-monorepo/
├── apps/
│   ├── web/           # Frontend
│   ├── api/           # Backend
│   └── worker/        # Background jobs
├── packages/
│   └── shared/        # Shared code
└── package.json

Deployment

code
1. Create project
2. For each app:
   - Create service
   - Set root directory to apps/<name>
   - Configure build command
   - Deploy

railway.toml per app

apps/web/railway.toml:

toml
[build]
buildCommand = "cd ../.. && npm run build:web"

[deploy]
startCommand = "npm run start:web"

apps/api/railway.toml:

toml
[build]
buildCommand = "cd ../.. && npm run build:api"

[deploy]
startCommand = "npm run start:api"

Pattern 5: Scheduled Tasks / Cron

For periodic jobs.

Architecture

code
┌─────────────┐
│   Cron Job  │──────▶ Runs on schedule
│  (Service)  │
└─────────────┘

Implementation

Option 1: Node.js with node-cron

javascript
import cron from 'node-cron';

// Run every hour
cron.schedule('0 * * * *', async () => {
  console.log('Running hourly task');
  await doWork();
});

// Keep process alive
process.stdin.resume();

Option 2: Separate cron service

code
# Deploy as service that runs periodically
# Use Railway's restart policy

Pattern 6: Static Site + API

JAMstack architecture.

Architecture

code
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   Static    │────▶│     API     │────▶│  Database   │
│   (Vite)    │     │  (Express)  │     │ (Postgres)  │
└─────────────┘     └─────────────┘     └─────────────┘
     CDN              Public             Private

Frontend Build

toml
# railway.toml
[build]
buildCommand = "npm run build"

[deploy]
startCommand = "npx serve dist -l $PORT"

Production Checklist

Before Going Live

code
□ Environment variables set (not hardcoded)
□ DATABASE_URL using reference variables
□ PORT not hardcoded
□ Health check endpoint implemented
□ Error handling in place
□ Logging configured
□ Secrets not in code
□ CORS configured correctly
□ Rate limiting (if public API)
□ SSL handled (Railway automatic for *.railway.app)

Performance

code
□ Database connection pooling
□ Redis for caching (if needed)
□ Appropriate resource allocation
□ Build optimization
□ Static assets optimized

Monitoring

code
□ Health checks configured
□ Log aggregation
□ Error tracking (Sentry, etc.)
□ Uptime monitoring

Service Communication Matrix

FromToUse
FrontendBackendPublic domain (HTTPS)
BackendDatabaseDATABASE_URL reference
ServiceService (internal)Private domain (HTTP)
ServiceExternal APIHTTPS
WorkerQueueREDIS_URL reference

Environment Variable Patterns

Per-Environment Config

code
# Production
NODE_ENV=production
LOG_LEVEL=error
DEBUG=false

# Staging
NODE_ENV=staging
LOG_LEVEL=debug
DEBUG=true

Service References

code
# Database
DATABASE_URL=${{Postgres.DATABASE_URL}}

# Cache
REDIS_URL=${{Redis.REDIS_URL}}

# Internal services
USERS_API=http://${{users-api.RAILWAY_PRIVATE_DOMAIN}}:3000

# External services (frontend)
NEXT_PUBLIC_API_URL=https://${{api.RAILWAY_PUBLIC_DOMAIN}}

Common Architectures by Framework

Next.js Full Stack

code
Next.js (API Routes + Frontend) → Postgres
Single service, DATABASE_URL reference

React + Express

code
React (Frontend) → Express (API) → Postgres
Two services + database

Django

code
Django (API + Admin) → Postgres + Redis
Single service + databases

FastAPI + Celery

code
FastAPI (API) → Redis (Broker) → Celery (Workers) → Postgres
Three services + databases

Quick Reference

PatternServicesWhen to Use
Frontend + Backend + DB3Most web apps
API + Worker + Queue3Background processing
Microservices4+Large scale apps
Monorepo2+Shared codebase
Cron Jobs1Scheduled tasks
Static + API2JAMstack