DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Your Bun.js Application with Vigilmon

How to Monitor Your Bun.js Application with Vigilmon

Bun is fast-but fast doesn't mean infallible. Whether you're running a Bun HTTP server, an Elysia.js API, or a Bun-powered CLI service, you need uptime monitoring to catch outages before your users do. This guide covers setting up health checks and monitoring for Bun applications.

Why Monitor Bun Applications?

Bun's performance advantages (faster startup, lower memory) make it popular for APIs and microservices-but the same reasons that make it lightweight also mean:

  • Less runtime scaffolding to catch crashes
  • Workers can exit silently on unhandled errors
  • Process restarts via PM2/systemd may not always succeed

Vigilmon adds an external layer: it checks your endpoint from outside your server, so even if your process manager fails to restart, you'll know.

Adding a Health Endpoint to Your Bun App

Basic Bun HTTP Server

` ypescript
// server.ts
const server = Bun.serve({
port: 3000,
fetch(req) {
const url = new URL(req.url);

if (url.pathname === "/health") {
  return new Response(JSON.stringify({
    status: "ok",
    uptime: process.uptime(),
    timestamp: new Date().toISOString(),
    bunVersion: Bun.version,
  }), {
    headers: { "Content-Type": "application/json" },
  });
}

// Your main app logic here
return new Response("Hello from Bun!");
Enter fullscreen mode Exit fullscreen mode

},
});

console.log(Server running on http://localhost:);
`

Elysia.js Health Endpoint

` ypescript
import { Elysia } from "elysia";

const app = new Elysia()
.get("/health", () => ({
status: "ok",
uptime: process.uptime(),
timestamp: new Date().toISOString(),
}))
.get("/", () => "Hello from Elysia!")
.listen(3000);

console.log(Running at http://localhost:);
`

Hono on Bun Health Endpoint

` ypescript
import { Hono } from "hono";
import { serve } from "@hono/node-server";

const app = new Hono();

app.get("/health", (c) => {
return c.json({
status: "ok",
runtime: "bun",
version: Bun.version,
uptime: process.uptime(),
});
});

export default app;
`

Deep Health Check with Database

` ypescript
// health.ts
import { Database } from "bun:sqlite";

const db = new Database("app.db");

export function healthCheck(): {
status: "ok" | "degraded" | "error";
checks: Record;
} {
const checks: Record = {};

// Check SQLite connection
try {
db.query("SELECT 1").get();
checks.database = true;
} catch {
checks.database = false;
}

// Check memory usage
const memUsage = process.memoryUsage();
checks.memory = memUsage.heapUsed < 500 * 1024 * 1024; // < 500MB

const allOk = Object.values(checks).every(Boolean);
const anyFail = Object.values(checks).some((v) => !v);

return {
status: allOk ? "ok" : anyFail ? "error" : "degraded",
checks,
};
}

// In your server:
const server = Bun.serve({
port: 3000,
fetch(req) {
const url = new URL(req.url);
if (url.pathname === "/health") {
const health = healthCheck();
const statusCode = health.status === "ok" ? 200 : 503;
return new Response(JSON.stringify(health), {
status: statusCode,
headers: { "Content-Type": "application/json" },
});
}
return new Response("OK");
},
});
`

Running Bun in Production

With PM2

javascript
// ecosystem.config.js
module.exports = {
apps: [{
name: "bun-app",
script: "bun",
args: "run server.ts",
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: "1G",
}]
};

ash
pm2 start ecosystem.config.js
pm2 save
pm2 startup

With systemd

`ini

/etc/systemd/system/bun-app.service

[Unit]
Description=Bun Application
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/app
ExecStart=/usr/local/bin/bun run server.ts
Restart=always
RestartSec=5
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
`

ash
systemctl enable bun-app
systemctl start bun-app

Setting Up Vigilmon Monitoring

  1. Go to vigilmon.online and create an account (free tier: 3 monitors)
  2. Click Add Monitor
  3. Configure:
    • URL: https://yourdomain.com/health
    • Interval: 1 minute (Pro) or 5 minutes (free)
    • Method: GET
    • Expected status: 200
    • Alert on: Any non-200 response

Alert Configuration

Connect Slack for instant alerts:

  1. Vigilmon ? Settings ? Notifications
  2. Add Slack webhook URL
  3. Test the integration

When your Bun process crashes, PM2 restarts it-but there's a window where requests fail. Vigilmon catches that window and alerts you.

Monitoring Bun Worker Threads

If you use Worker in Bun, the main process can stay up while workers crash silently. Add a separate health check that pings your workers:

` ypescript
// worker-health.ts
let workerHealthy = true;

const worker = new Worker("./worker.ts");
worker.onmessage = (event) => {
if (event.data === "ping") workerHealthy = true;
};
worker.onerror = () => { workerHealthy = false; };

// Ping worker every 30 seconds
setInterval(() => {
workerHealthy = false; // Reset, wait for pong
worker.postMessage("ping");
}, 30_000);

export { workerHealthy };
`

Then include workerHealthy in your /health response.

Recommended Monitoring Setup

Monitor Check Interval Alert
Main endpoint 1 min Slack + email
Health endpoint 1 min Slack + email
SSL certificate Daily Email 30d before expiry
Response time 1 min Alert if >2s

Summary

  • Add a /health endpoint to every Bun service
  • Return 200 for healthy, 503 for degraded
  • Run with PM2 or systemd for process supervision
  • Add Vigilmon for external uptime monitoring
  • Set up Slack alerts to catch the restart window

Monitor your Bun app at vigilmon.online - free for 3 monitors, no credit card required.

Top comments (0)