DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Your Railway App with Vigilmon

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);
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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"),
    })
})
Enter fullscreen mode Exit fullscreen mode

Configuring Vigilmon for Railway

  1. Go to vigilmon.online and create a monitor.
  2. Type: HTTP(S)
  3. URL: your Railway app domain (e.g., https://your-app.railway.app/health)
  4. Check interval: 2 minutes
  5. 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
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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 };
};
Enter fullscreen mode Exit fullscreen mode

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)