| name | railway-deployment |
| description | Railway deployment workflows, nixpacks configuration, environment management, and production troubleshooting Use when this capability is needed. |
| metadata | {"author":"ainative-studio"} |
Railway Deployment Skill
When to Use This Skill
Use this skill when:
- Deploying applications to Railway platform
- Configuring nixpacks.toml for custom builds
- Managing environment variables across services
- Debugging deployment failures
- Setting up multi-service Railway projects
- Troubleshooting production issues
- Configuring database migrations on Railway
- Setting up health checks and monitoring
Core Principles
1. Build Configuration First
Always start with proper nixpacks configuration:
- Specify all system dependencies in
nixPkgs
- Define build phases explicitly
- Test locally with nixpacks CLI when possible
2. Environment Variable Management
- Use Railway's service references:
${{ServiceName.VARIABLE}}
- Never hardcode secrets or URLs
- Use Railway secrets for sensitive data
- Configure all environment variables before deployment
3. Port Binding
Always bind to Railway's PORT environment variable:
port = int(os.environ.get('PORT', 8000))
4. Health Checks
Implement health check endpoints for Railway to monitor:
@app.get("/health")
async def health_check():
return {"status": "healthy"}
Common Deployment Workflows
Initial Deployment
- Create nixpacks.toml in project root
- Configure environment variables in Railway dashboard
- Add Procfile or start command (optional if using nixpacks)
- Deploy via GitHub integration or CLI
- Monitor build logs for errors
- Verify deployment with health check
Multi-Service Deployment
project/
├── backend/
│ ├── nixpacks.toml
│ └── requirements.txt
├── frontend/
│ ├── nixpacks.toml
│ └── package.json
└── railway.toml # Optional: multi-service config
Configure service references:
VITE_API_URL=https://${{backend.RAILWAY_PUBLIC_DOMAIN}}
FRONTEND_URL=https://${{frontend.RAILWAY_PUBLIC_DOMAIN}}
Database Migration Strategy
[phases.build]
cmds = [
'pip install -r requirements.txt',
'alembic upgrade head'
]
Alternative: Separate migration service
railway run alembic upgrade head
nixpacks Configuration Patterns
Python + PostgreSQL
[phases.setup]
nixPkgs = ['python310', 'postgresql']
nixLibs = ['libpq']
[phases.install]
cmds = ['pip install -r requirements.txt']
[start]
cmd = 'uvicorn main:app --host 0.0.0.0 --port $PORT'
Node.js + TypeScript
[phases.setup]
nixPkgs = ['nodejs-18_x']
[phases.install]
cmds = ['npm ci']
[phases.build]
cmds = ['npm run build']
[start]
cmd = 'node dist/index.js'
Full-Stack (Python Backend + React Frontend)
[phases.setup]
nixPkgs = ['python310', 'nodejs-18_x', 'postgresql']
nixLibs = ['libpq']
[phases.install]
cmds = [
'pip install -r requirements.txt',
'cd frontend && npm ci'
]
[phases.build]
cmds = [
'cd frontend && npm run build',
'alembic upgrade head'
]
[start]
cmd = 'gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:$PORT'
Environment Variable Patterns
Database Connection
DATABASE_URL=${{Postgres.DATABASE_URL}}
DATABASE_PRIVATE_URL=${{Postgres.DATABASE_PRIVATE_URL}}
Redis Connection
REDIS_URL=${{Redis.REDIS_URL}}
REDIS_PRIVATE_URL=${{Redis.REDIS_PRIVATE_URL}}
Service-to-Service Communication
BACKEND_PRIVATE_URL=http://${{backend.RAILWAY_PRIVATE_DOMAIN}}
BACKEND_PUBLIC_URL=https://${{backend.RAILWAY_PUBLIC_DOMAIN}}
Application Configuration
ENVIRONMENT=production
DEBUG=false
JWT_SECRET_KEY=${{secrets.JWT_SECRET}}
ALLOWED_HOSTS=${{RAILWAY_PUBLIC_DOMAIN}}
CORS_ORIGINS=https://${{frontend.RAILWAY_PUBLIC_DOMAIN}}
Troubleshooting Guide
Build Failures
Error: "Package not found"
Error: "Command failed"
- Check build logs for specific error
- Verify commands work locally
- Ensure correct working directory
Runtime Failures
Error: "Application failed to respond"
- Verify binding to
0.0.0.0 not localhost
- Check PORT environment variable usage
- Ensure health check endpoint exists
Error: "Database connection failed"
- Verify DATABASE_URL is set
- Check database service is running
- Use private URL for better performance
Deployment Best Practices
-
Always test locally first
nixpacks build . --name myapp
docker run -p 8000:8000 myapp
-
Use railway.toml for monorepos
[build]
builder = "nixpacks"
buildCommand = "cd backend && pip install -r requirements.txt"
[deploy]
startCommand = "cd backend && uvicorn main:app --host 0.0.0.0 --port $PORT"
restartPolicyType = "on-failure"
-
Set up health checks
@app.get("/health")
async def health():
try:
await db.execute("SELECT 1")
return {"status": "healthy", "database": "connected"}
except:
return {"status": "unhealthy", "database": "disconnected"}
-
Configure logging
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
-
Use Railway CLI for debugging
railway login
railway link
railway logs
railway run python manage.py shell
Production Deployment Checklist
Pre-Deployment
During Deployment
Post-Deployment
Rollback Procedure
- Go to Railway dashboard
- Navigate to deployments tab
- Click "Redeploy" on previous working deployment
- Monitor rollback completion
- Verify application health
Advanced Patterns
Zero-Downtime Deployments
Railway handles this automatically with:
- Health check monitoring
- Gradual traffic shifting
- Automatic rollback on health check failures
Custom Domains
CNAME record: your-domain.com -> your-app.up.railway.app
Private Networking
Use Railway's private networking for service-to-service communication:
INTERNAL_API_URL=http://${{backend.RAILWAY_PRIVATE_DOMAIN}}
Environment-Specific Configuration
ENVIRONMENT=${{RAILWAY_ENVIRONMENT}}
Common Integration Patterns
PostgreSQL
from sqlalchemy import create_engine
import os
DATABASE_URL = os.environ.get('DATABASE_URL')
if DATABASE_URL and DATABASE_URL.startswith('postgres://'):
DATABASE_URL = DATABASE_URL.replace('postgres://', 'postgresql://')
engine = create_engine(DATABASE_URL)
Redis
import os
import redis
REDIS_URL = os.environ.get('REDIS_URL')
redis_client = redis.from_url(REDIS_URL)
File Storage (Railway Volumes)
[deploy]
volumes = [
{ name = "data", mountPath = "/app/data" }
]
Monitoring and Observability
Logging Best Practices
import logging
import sys
logging.basicConfig(
stream=sys.stdout,
level=logging.INFO,
format='{"time": "%(asctime)s", "level": "%(levelname)s", "message": "%(message)s"}'
)
Metrics Collection
from prometheus_client import Counter, Histogram, generate_latest
request_count = Counter('http_requests_total', 'Total HTTP requests')
request_duration = Histogram('http_request_duration_seconds', 'HTTP request duration')
@app.get("/metrics")
async def metrics():
return Response(generate_latest(), media_type="text/plain")
Railway CLI Commands
railway login
railway link
railway up
railway up --detach
railway variables set KEY=value
railway variables delete KEY
railway logs
railway logs --deployment <id>
railway shell
railway service
railway domain
Security Considerations
- Never commit secrets - Use Railway secrets
- Use HTTPS only - Railway provides automatic SSL
- Configure CORS properly - Restrict to known domains
- Validate environment variables - Check all required vars on startup
- Use private networking - For service-to-service communication
- Enable Railway's Web Application Firewall - If available
- Rotate secrets regularly - Update JWT keys, API keys, etc.
Performance Optimization
Build Time Optimization
[phases.install]
cmds = [
'pip install --cache-dir /root/.cache/pip -r requirements.txt'
]
Runtime Optimization
import multiprocessing
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = 'uvicorn.workers.UvicornWorker'
Database Connection Pooling
from sqlalchemy import create_engine
engine = create_engine(
DATABASE_URL,
pool_size=10,
max_overflow=20,
pool_pre_ping=True
)
Skill Output Format
When using this skill, provide:
- nixpacks.toml configuration - Customized for the project
- Environment variable list - All required variables with Railway references
- Deployment command - Exact commands to run
- Health check implementation - Code for monitoring
- Troubleshooting steps - For any potential issues
- Rollback procedure - How to revert if needed
References
See the references/ directory for detailed documentation on:
- nixpacks configuration patterns
- Environment variable management
- Troubleshooting guides
- Production deployment checklists
Converted and distributed by TomeVault — claim your Tome and manage your conversions.