DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Fly.io Deployments with Vigilmon

Fly.io has become a favorite platform for deploying full-stack applications, APIs, and background services. Its global anycast network, generous free tier, and developer-friendly CLI make it easy to get apps into production. But once your app is on Fly.io, how do you know it stays up?

This guide covers setting up uptime monitoring for Fly.io deployments using Vigilmon.

How Fly.io Deployments Can Fail

Fly.io is reliable, but failures happen at multiple layers:

  • Machine crashes: Your app process panics or runs out of memory
  • Deployment rollouts: A bad deploy rolls out and crashes on startup
  • Scaling events: New machines spin up with wrong environment variables
  • Regional failures: Specific Fly.io regions become unreachable
  • Volume mount issues: Persistent volumes fail to attach
  • Resource limits: CPU/memory limits cause OOM kills

Fly.io has internal health checks that restart machines — but they don't alert your team. Vigilmon provides the external monitoring and notifications layer.

Step 1: Add a Health Check Endpoint to Your App

Every app running on Fly.io should expose a /health endpoint. Here are examples for common stacks:

Node.js / Express

app.get('/health', (req, res) => {
  res.json({ status: 'ok', region: process.env.FLY_REGION });
});
Enter fullscreen mode Exit fullscreen mode

Python / FastAPI

@app.get("/health")
async def health():
    return {"status": "ok", "region": os.getenv("FLY_REGION")}
Enter fullscreen mode Exit fullscreen mode

Go

http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]string{
        "status": "ok",
        "region": os.Getenv("FLY_REGION"),
    })
})
Enter fullscreen mode Exit fullscreen mode

Ruby on Rails

# config/routes.rb
get '/health', to: proc { [200, {'Content-Type' => 'application/json'}, ['{"status":"ok"}']] }
Enter fullscreen mode Exit fullscreen mode

Note: FLY_REGION is a built-in Fly.io environment variable — great for debugging multi-region issues.

Step 2: Configure Fly.io Internal Health Checks

Add health checks to your fly.toml:

[[services]]
  internal_port = 8080
  protocol = "tcp"

  [[services.http_checks]]
    interval = 15000
    timeout = 2000
    grace_period = "5s"
    method = "get"
    path = "/health"
    protocol = "http"
    restart_limit = 3
Enter fullscreen mode Exit fullscreen mode

These internal checks restart your machine if it fails. But they don't notify anyone — that's Vigilmon's job.

Step 3: Set Up Vigilmon External Monitoring

  1. Sign up at vigilmon.online (free plan available)
  2. Click New Monitor
  3. Configure:
    • URL: https://yourapp.fly.dev/health
    • Type: HTTP
    • Interval: 60 seconds
    • Expected status: 200
  4. Add alert channels:
    • Email: default
    • Slack: Settings → Notifications → Add Slack webhook
  5. Save

Vigilmon now monitors your Fly.io app from outside the infrastructure.

Multi-Region Monitoring

Fly.io can run your app in multiple regions. Vigilmon monitors from a single point, but you can add monitors for each region's health:

https://yourapp.fly.dev/health  (global anycast)
Enter fullscreen mode Exit fullscreen mode

If you have region-pinned endpoints, monitor each one separately:

https://iad.yourapp.fly.dev/health   (US East)
https://lhr.yourapp.fly.dev/health   (UK)
https://sin.yourapp.fly.dev/health   (Singapore)
Enter fullscreen mode Exit fullscreen mode

Common Fly.io Failure Scenarios and How Vigilmon Catches Them

Deployment Failure

You push a new deploy. The new machine starts, but your app crashes on startup (e.g., missing SECRET_KEY env var). The old machine is killed. Fly.io doesn't roll back automatically by default.

Vigilmon catches the 500 errors or timeouts within the next check interval and alerts you immediately.

OOM Kill

Your app runs out of memory (e.g., memory leak after days of uptime). The Fly.io machine is OOM-killed. Fly.io restarts it, but there's a gap.

Vigilmon detects the gap and alerts your team — even if the machine recovers before you notice.

Volume Mount Failure

If your app uses a persistent volume and the volume fails to mount, your app may start but fail on any disk access. Health checks that verify disk writes catch this:

// Test disk access in health check
func healthHandler(w http.ResponseWriter, r *http.Request) {
    // Try writing to a file on the mounted volume
    err := os.WriteFile("/data/.healthcheck", []byte("ok"), 0644)
    if err != nil {
        w.WriteHeader(http.StatusServiceUnavailable)
        json.NewEncoder(w).Encode(map[string]string{"status": "error", "volume": err.Error()})
        return
    }
    json.NewEncoder(w).Encode(map[string]string{"status": "ok"})
}
Enter fullscreen mode Exit fullscreen mode

Setting Up Alerts

Slack

Connect your Vigilmon account to Slack:

  1. Settings → Notifications → Add Slack
  2. Enter your Slack webhook URL
  3. Choose the channel (e.g., #fly-alerts)

Webhook (for PagerDuty or custom tools)

  1. Settings → Notifications → Add Webhook
  2. Enter your PagerDuty Events API endpoint
  3. Vigilmon POSTs JSON on state changes

Public Status Page

Vigilmon generates a public status page. Add it to your Fly.io app's response headers or landing page:

https://status.vigilmon.online/your-org
Enter fullscreen mode Exit fullscreen mode

Cost Comparison

Fly.io monitoring options:

Approach Cost Who gets notified Reaction
Fly.io internal checks Free Nobody Restarts machine
Fly.io metrics Free Nobody Observability only
Vigilmon Free tier Your team Instant alert

Fly.io's built-in checks are excellent at restarting failed machines. Vigilmon is what tells your team something happened.

Summary

Fly.io is a great platform, but external monitoring is still essential. Set up Vigilmon in 3 steps:

  1. Add a /health endpoint to your app
  2. Configure fly.toml internal checks for automatic restarts
  3. Add Vigilmon external monitoring so your team gets alerted

Start monitoring your Fly.io app →

Top comments (0)