Monitoring Your Render.com Application with Vigilmon
Render is a popular Heroku alternative that handles build, deploy, and TLS automatically. But like Heroku before it, free and starter-tier Render services spin down after inactivity — and when a real outage hits, Render's internal dashboards don't page you.
You need external monitoring: something that probes your live URL from outside Render's infrastructure, knows the difference between a cold start and a crash, and wakes you up when something actually breaks.
This tutorial covers:
- A health endpoint for Render web services
- Vigilmon HTTP monitoring with cold-start tolerance
- Alerts that don't false-fire on every spin-up
- Heartbeat monitoring for Render cron jobs
Step 1: Add a health endpoint to your app
Every Render web service needs a /health route that returns 200 when the app is running correctly and 503 when something is wrong.
Node.js / Express:
// server.js
import express from 'express';
const app = express();
app.get('/health', async (req, res) => {
try {
// optional: check DB or cache connectivity here
res.json({
status: 'ok',
env: process.env.RENDER_SERVICE_NAME || 'local',
timestamp: new Date().toISOString(),
});
} catch {
res.status(503).json({ status: 'error' });
}
});
app.listen(process.env.PORT || 3000);
Python / Flask:
# app.py
from flask import Flask, jsonify
import os, datetime
app = Flask(__name__)
@app.route('/health')
def health():
return jsonify({
'status': 'ok',
'service': os.getenv('RENDER_SERVICE_NAME', 'app'),
'timestamp': datetime.datetime.utcnow().isoformat(),
})
Python / FastAPI:
# main.py
from fastapi import FastAPI, Response
import os, datetime
app = FastAPI()
@app.get("/health")
def health(response: Response):
# check dependencies; set response.status_code = 503 on failure
return {
"status": "ok",
"service": os.getenv("RENDER_SERVICE_NAME", "app"),
"timestamp": datetime.datetime.utcnow().isoformat(),
}
Render injects PORT and RENDER_SERVICE_NAME automatically. Always bind to PORT.
Step 2: Enable Render's native health check
Render supports health check paths that control deploy promotion. In your service settings:
- Go to Settings → Health & Alerts
- Set Health Check Path to
/health - Set the failure threshold (e.g., 3 consecutive failures)
This prevents a broken deploy from going live. It doesn't give you external alerts — that's what Vigilmon handles.
Step 3: Set up Vigilmon monitoring
With your app deployed on Render, connect it to Vigilmon:
- Sign up at vigilmon.online — free, no card required
- Click New Monitor → HTTP
- URL:
https://your-service.onrender.com/health - Check interval: 1 minute (paid) or 5 minutes (free)
- Expected status:
200 - Save
If you've connected a custom domain, monitor that instead — it covers both your DNS and your Render service:
https://api.yourdomain.com/health
Step 4: Tune for cold starts
Render's free and starter web services spin down after 15 minutes of inactivity. The first request after a spin-down triggers a cold start that can take 10–30 seconds.
To avoid false alerts from cold starts:
- In Vigilmon's monitor settings, set Timeout to
30seconds - Set Confirm Down After to
2consecutive failures
With these settings, Vigilmon waits for two consecutive failures before alerting. A single cold start shows up as a slow response, not a false-positive outage.
If you're on a Render paid plan with always-on instances, you can lower the timeout to 10 seconds for faster real outage detection.
Step 5: Configure alerts
In Vigilmon, go to Notifications → New Channel:
Slack:
1. Create an incoming webhook at api.slack.com/apps
2. Paste the URL into Vigilmon → Notifications → Slack
3. Enable it on your Render monitors
Email:
1. Add your address as a notification channel
2. Enable on monitors
What you see when a real outage happens:
🔴 DOWN: your-service.onrender.com/health
Status: 0 (connection timeout)
Region: EU-West
5 minutes ago
And on recovery:
✅ RECOVERED: your-service.onrender.com/health
Downtime: 12 minutes
The key difference from a cold start: a real outage produces multiple consecutive failures across different Vigilmon regions. A cold start produces a slow (but successful) response from one region.
Step 6: Monitor Render cron jobs
Render supports cron jobs as a separate service type. A cron job that silently crashes or stops running won't surface in your HTTP monitor — the web service stays green while background work stops.
Add a heartbeat ping to your cron job:
Node.js:
// cron/main.js
import fetch from 'node-fetch';
async function main() {
try {
await runScheduledWork();
const heartbeatUrl = process.env.VIGILMON_CRON_HEARTBEAT;
if (heartbeatUrl) {
await fetch(heartbeatUrl);
}
} catch (err) {
console.error('Cron job failed:', err);
process.exit(1);
}
}
async function runScheduledWork() {
// your job logic
}
main();
Python:
# cron/main.py
import os, requests
def main():
try:
run_scheduled_work()
heartbeat_url = os.getenv('VIGILMON_CRON_HEARTBEAT')
if heartbeat_url:
requests.get(heartbeat_url, timeout=5)
except Exception as e:
print(f'Cron job failed: {e}')
raise
def run_scheduled_work():
pass # your logic
if __name__ == '__main__':
main()
In Vigilmon:
- Click New Monitor → Heartbeat
- Set the interval to match your cron schedule
- Copy the ping URL
- Add
VIGILMON_CRON_HEARTBEAT=<url>as a Render environment variable
Step 7: Watch for spin-down patterns in Render
Render free services spin down on idle. If your health check interval is 5 minutes (free Vigilmon tier), the service may spin down between checks and Vigilmon's probe will wake it up each time — masking the spin-down behavior.
To understand your app's idle behavior:
- Add Vigilmon's Response Time chart to your dashboard
- Look for latency spikes on a regular pattern — those are cold starts
- Upgrade Render (to always-on) or Vigilmon (1-minute interval) if the pattern concerns you
The charts give you evidence for the upgrade conversation.
Step 8: Public status page
Go to Status Pages → New Status Page in Vigilmon, add your monitors, and share the URL:
Something broken? Check https://status.yourdomain.com
Each monitor generates a live status badge:

What you've built
| What | How |
|------|-----|
| Health endpoint | Framework-native /health route |
| Render deploy protection | Render health check path |
| External uptime monitoring | Vigilmon HTTP monitor |
| Cold-start tolerance | 30s timeout + 2-failure confirm threshold |
| Slack/email alerts | Vigilmon notification channels |
| Cron job monitoring | Heartbeat ping in cron service |
| Spin-down visibility | Vigilmon response time charts |
| Status page | Vigilmon public status page |
Render takes care of deployment. Vigilmon takes care of watching it from the outside.
Next steps
- Add separate Vigilmon monitors for staging and production Render services
- Set up response time alerts — Render cold starts that regularly take >10 seconds are a signal to upgrade to always-on
- Add heartbeats for every Render cron service that does work you'd notice missing
Get started free at vigilmon.online.