tutorial

Monitoring PM2 with Vigilmon

PM2 manages your Node.js processes in production — but the apps it runs and PM2 itself need external monitoring. Here's how to monitor PM2-managed applications, dashboard availability, and process restarts with Vigilmon.

PM2 is the standard process manager for Node.js production deployments, handling clustering, zero-downtime reloads, log management, and automatic process restarts. It gives your Node.js apps resilience — but PM2 can't tell you when an app's upstream endpoint is returning errors, when a process is stuck in a restart loop, or when your SSL certificate is about to expire. Vigilmon fills that gap: monitoring your PM2-managed application endpoints from outside, tracking process health via heartbeats, and alerting on SSL certificate issues before users notice.

What You'll Set Up

  • HTTP uptime monitor for PM2-managed application endpoints
  • PM2 web dashboard availability check (pm2-web or PM2 Plus)
  • Process health monitoring via upstream health endpoints
  • Heartbeat monitoring for PM2 process restarts and cron-scheduled jobs
  • SSL certificate alerts for managed application domains

Prerequisites

  • PM2 2.0+ installed globally (npm install -g pm2)
  • At least one Node.js application running under PM2 (pm2 list)
  • Applications exposing HTTP endpoints (recommended: a /health route)
  • A free Vigilmon account

Step 1: Add a Health Endpoint to Your Node.js Application

PM2-managed apps should expose a /health endpoint that Vigilmon can probe. Here are minimal examples for common Node.js frameworks:

Express

app.get('/health', (req, res) => {
  res.json({ status: 'ok', uptime: process.uptime(), pid: process.pid });
});

Fastify

fastify.get('/health', async () => {
  return { status: 'ok', uptime: process.uptime() };
});

NestJS

@Get('/health')
health(): object {
  return { status: 'ok' };
}

The health endpoint should also check internal dependencies (database, Redis, external APIs) and return a non-200 status if they're unavailable:

app.get('/health', async (req, res) => {
  try {
    await db.query('SELECT 1');
    res.json({ status: 'ok' });
  } catch (err) {
    res.status(503).json({ status: 'error', detail: 'database unavailable' });
  }
});

After adding the endpoint, restart the app with PM2:

pm2 restart your-app-name

Step 2: Monitor PM2-Managed Application Endpoints

Add a Vigilmon monitor for each critical PM2-managed application:

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter your application's health URL: https://yourapp.com/health.
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Enable Keyword check and enter "status":"ok" to validate the response body.
  7. Click Save.

Repeat for each PM2-managed application in your pm2 list output.

For clustered applications (PM2 cluster mode), the load balancer IP or domain is the right URL — you're testing the whole cluster, not individual instances.


Step 3: Monitor the PM2 Web Dashboard

If you use pm2-web (an open-source PM2 web UI) or PM2 Plus (the hosted dashboard), add a monitor for the dashboard itself:

pm2-web (self-hosted)

pm2-web runs on port 8080 by default. Install and start it:

npm install -g pm2-web
pm2-web --config pm2-web-config.json

Add a Vigilmon monitor:

  1. Click Add MonitorHTTP / HTTPS.
  2. Set the URL to http://your-server:8080 (or the proxied HTTPS URL).
  3. Set Expected HTTP status to 200.
  4. Set Check interval to 2 minutes.
  5. Click Save.

PM2 Plus (keymetrics.io)

If using PM2 Plus, add a monitor for the PM2 Plus web app at app.pm2.io and check that your linked server appears as connected. This is an external dependency monitoring pattern — you're checking that your PM2 agent can reach the PM2 Plus cloud, not just that the PM2 process is running.


Step 4: SSL Certificate Alerts for Managed Application Domains

PM2-managed Node.js apps commonly serve traffic over HTTPS either via Node.js's built-in TLS or through a reverse proxy (nginx, Caddy, Traefik). Monitor SSL certificates for each application domain:

  1. Open the HTTPS monitor for each application (created in Step 2).
  2. Scroll to the SSL certificate section.
  3. Enable Monitor SSL certificate.
  4. Set Alert when certificate expires in less than 21 days.
  5. Click Save.

List all domains your PM2 apps serve:

pm2 list
# Note each app name, then check your nginx/proxy config for their domains

Check certificate expiry manually:

echo | openssl s_client -connect yourapp.com:443 2>/dev/null \
  | openssl x509 -noout -enddate

Add a separate Vigilmon SSL monitor for each domain, especially for apps with custom domains not on wildcard certificates.


Step 5: Heartbeat Monitoring for PM2 Process Restarts

PM2 restarts processes automatically on crash — but a process stuck in a restart loop (status: errored cycling to online) is doing no useful work. Use a cron heartbeat that only pings Vigilmon when the app is healthy, not just running:

Create the heartbeat monitor:

  1. In Vigilmon, click Add MonitorCron Heartbeat.
  2. Set the name to your app name (e.g., api-server).
  3. Set Expected ping interval to 2 minutes.
  4. Copy the heartbeat URL (e.g. https://vigilmon.online/heartbeat/abc123).

Add a PM2 ecosystem health script:

Create /usr/local/bin/pm2-heartbeat.sh:

#!/bin/bash
APP_NAME="your-app-name"
HEARTBEAT_URL="https://vigilmon.online/heartbeat/abc123"

# Only ping if the app is online (not errored/stopped)
STATUS=$(pm2 jlist 2>/dev/null | node -e "
  const apps = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8'));
  const app = apps.find(a => a.name === '${APP_NAME}');
  console.log(app ? app.pm2_env.status : 'not_found');
")

if [ "$STATUS" = "online" ]; then
  curl -s "$HEARTBEAT_URL" --max-time 5
fi
chmod +x /usr/local/bin/pm2-heartbeat.sh

Add to crontab:

* * * * * /usr/local/bin/pm2-heartbeat.sh

Alternative: ping from the application on each request cycle:

For cron-scheduled PM2 jobs (apps with cron_restart in their ecosystem config), ping from the app after each successful run:

const https = require('https');

async function runJob() {
  await processQueue();
  // Confirm successful run to Vigilmon
  https.get('https://vigilmon.online/heartbeat/abc123').on('error', () => {});
}

This catches the case where PM2 restarts the process successfully but the application logic is failing — a silent failure that PM2's process manager won't detect.


Step 6: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and add Slack, email, PagerDuty, or a webhook.
  2. Group all monitors for a server in a Vigilmon project.
  3. Set Consecutive failures before alert to 2 on application endpoint monitors — PM2 zero-downtime reloads cause brief gaps.
  4. Set Consecutive failures before alert to 1 on heartbeat monitors.
  5. Enable Recovery notifications so you know when PM2 brings an app back online.

For high-traffic production apps, set the check interval to 30 seconds for the /health endpoint monitor.


Summary

| Monitor | Target | What It Catches | |---|---|---| | App health endpoint | https://yourapp.com/health | App errors, dependency failures | | PM2 web dashboard | http://server:8080 | Dashboard/monitoring UI down | | SSL certificate | Each app domain | Certificate expiry | | Cron heartbeat | Vigilmon heartbeat URL | Restart loop, logic failure |

PM2 makes Node.js applications resilient to process crashes — but it can't detect upstream dependency failures, restart loops, or application-level logic errors. With Vigilmon monitoring each application's health endpoint from outside the server, tracking SSL certificates, and receiving heartbeats only when apps are genuinely healthy, you get the production-grade observability layer that PM2's built-in tools don't provide.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →