Railway has become a developer favorite for deploying containerized apps — simple pricing, great DX, and built-in support for databases, cron jobs, and persistent volumes. But like any cloud platform, Railway deployments can fail in ways that aren't immediately obvious: container crashes, memory limits, failed healthchecks that prevent new deploy rollouts, or database connection issues.
Here's how to monitor Railway apps with Vigilmon.
Why Railway Apps Need External Monitoring
Railway provides basic deployment metrics, but you still need external monitoring for:
- Availability confirmation: Verify that traffic is reaching your app, not just that the container is running
- Multi-region health: Railway's monitoring is internal; you want checks from multiple global locations
- Dependency failures: Your Railway app may be up but unable to reach a Railway database that's degraded
- Deployment regression detection: A new deploy that breaks an endpoint won't be caught by Railway's platform monitoring
Setting Up Health Endpoints
Node.js / Express on Railway
import express from 'express';
const app = express();
app.get('/health', async (req, res) => {
const checks: Record<string, string> = {
status: 'ok',
timestamp: new Date().toISOString(),
environment: process.env.RAILWAY_ENVIRONMENT ?? 'unknown',
};
// Check Railway database connectivity
try {
await pool.query('SELECT 1');
checks.database = 'ok';
} catch {
return res.status(503).json({ ...checks, database: 'error', status: 'degraded' });
}
res.json(checks);
});
const PORT = process.env.PORT ?? 3000;
app.listen(PORT);
Note: Railway sets PORT automatically — always use process.env.PORT.
Django on Railway
# urls.py
from django.http import JsonResponse
from django.db import connection
import datetime
def health(request):
try:
with connection.cursor() as cursor:
cursor.execute('SELECT 1')
db_status = 'ok'
http_status = 200
except Exception:
db_status = 'error'
http_status = 503
return JsonResponse({
'status': 'ok' if db_status == 'ok' else 'degraded',
'database': db_status,
'timestamp': datetime.datetime.utcnow().isoformat(),
}, status=http_status)
Go on Railway
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
if err := db.PingContext(r.Context()); err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
json.NewEncoder(w).Encode(map[string]string{
"status": "error",
"database": "unreachable",
})
return
}
json.NewEncoder(w).Encode(map[string]string{
"status": "ok",
"environment": os.Getenv("RAILWAY_ENVIRONMENT"),
})
})
Configuring Vigilmon for Railway
- Go to vigilmon.online and create a monitor.
- Type: HTTP(S)
- URL: your Railway app domain (e.g.,
https://your-app.railway.app/health) - Check interval: 2 minutes
- Expected status: 200
Railway generates a .railway.app domain automatically, but you should use your custom domain in production monitoring to test the full DNS path.
Using Railway's Built-in Health Checks
Railway supports health check configuration in railway.toml:
[deploy]
healthcheckPath = "/health"
healthcheckTimeout = 30
restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 3
This tells Railway to wait for /health to return 200 before routing traffic to a new deploy. If Vigilmon shows your app going down after a deploy, check Railway's deployment logs — the health check may be failing.
Monitoring Railway Cron Jobs
Railway supports cron jobs as separate services. Use Vigilmon heartbeat monitoring to confirm they run on schedule:
# Your Railway cron job script
import requests
def send_weekly_digest():
# ... your job logic ...
# Signal successful completion
requests.get('https://vigilmon.online/hb/YOUR_HEARTBEAT_ID', timeout=10)
send_weekly_digest()
Configure the heartbeat to expect a ping every 7 days. If Railway fails to trigger the cron, or the job errors out before the heartbeat ping, Vigilmon alerts you.
Monitoring Railway Databases
Railway provisions PostgreSQL, MySQL, Redis, and MongoDB. These can have connection limits or resource constraints. Add database-specific health checks:
// Check Railway PostgreSQL
const dbHealth = async (): Promise<{ status: string; latencyMs: number }> => {
const start = Date.now();
await pool.query('SELECT 1');
return { status: 'ok', latencyMs: Date.now() - start };
};
If your Railway database is approaching its storage or connection limits, query times will increase. Vigilmon's response time trend alerts you before hard failures occur.
Environment-Specific Monitoring
Railway supports multiple environments (production, staging, PR environments). Set up monitors for each stable environment:
| Environment | URL | Monitor Interval |
|---|---|---|
| Production | https://your-app.com/health |
1 minute |
| Staging | https://staging.your-app.com/health |
5 minutes |
Skip PR environment monitoring since URLs change with each PR.
Alert Thresholds for Railway Apps
Railway runs on shared infrastructure with some variability. Suggested thresholds:
| Metric | Warning | Alert |
|---|---|---|
| Response time | 1000ms | 3000ms |
| Availability | < 99.5% | < 99% |
| HTTP status | 4xx | 5xx |
Start Monitoring Your Railway App
Free tier at vigilmon.online — covers your Railway production and staging environments without a credit card.
Top comments (0)