Elysia is the fastest HTTP framework for Bun, built for high-throughput APIs and type-safe end-to-end development. Its performance profile makes it tempting to skip observability tooling — "it's fast, surely nothing breaks." But outages don't care how fast your framework is. A database connection pool exhausted at midnight, a failed deployment that returns 500s on one route, an SSL certificate that expired while you were heads-down shipping — these failures need an independent observer.
Vigilmon polls your app's health endpoint every minute from external locations and alerts you the moment it breaks. This tutorial walks you through wiring Elysia into Vigilmon in under 15 minutes.
What You'll Build
- A
/healthendpoint in Elysia that reflects real dependency state - A Vigilmon HTTP monitor with multi-region polling
- A keyword monitor for your HTML frontend (if applicable)
- Email and Slack webhook alert channels
Prerequisites
- Bun v1.0+ installed
- An Elysia project (
bun create elysia my-appor existing) - A free Vigilmon account (5 monitors free, no credit card)
Step 1: Add a Health Endpoint
Elysia's decorator system makes adding a health route clean and type-safe. Add it early in your route definitions so it's never shadowed by a wildcard handler.
// src/index.ts
import { Elysia } from 'elysia'
const app = new Elysia()
app.get('/health', async () => {
const checks: Record<string, string> = {}
let ok = true
// Database ping — adapt this to your actual DB client
try {
const start = performance.now()
// await db.execute('SELECT 1') ← your DB query here
checks.database = `ok (${Math.round(performance.now() - start)}ms)`
} catch (err) {
checks.database = `error: ${(err as Error).message}`
ok = false
}
// External dependency probe
try {
const res = await fetch('https://api.yourupstream.com/ping', {
signal: AbortSignal.timeout(3000),
})
checks.upstream = res.ok ? 'ok' : `http_${res.status}`
if (!res.ok) ok = false
} catch (err) {
checks.upstream = `error: ${(err as Error).message}`
ok = false
}
return new Response(
JSON.stringify({
status: ok ? 'ok' : 'degraded',
checks,
timestamp: new Date().toISOString(),
}),
{
status: ok ? 200 : 503,
headers: { 'Content-Type': 'application/json' },
}
)
})
app.get('/', () => 'Hello from Elysia!')
app.listen(3000)
console.log(`Server running at http://localhost:${app.server?.port}`)
Start the server and test it:
bun run src/index.ts
curl -s http://localhost:3000/health | bun -e "const t = await Bun.stdin.text(); console.log(JSON.stringify(JSON.parse(t), null, 2))"
Expected output when healthy:
{
"status": "ok",
"checks": {
"database": "ok (1ms)",
"upstream": "ok"
},
"timestamp": "2025-06-30T10:00:00.000Z"
}
When a dependency fails, status becomes "degraded" and the HTTP response code is 503. Vigilmon treats any non-2xx status as a downtime event and triggers the alert chain immediately.
Step 2: Use Elysia's Lifecycle Hooks for Accurate Timing
Elysia's onRequest / onResponse lifecycle hooks let you measure real handler latency and expose it in the health payload — useful for detecting performance regressions before they become outages.
import { Elysia } from 'elysia'
let lastRequestMs: number | null = null
const app = new Elysia()
.onRequest(() => {
lastRequestMs = performance.now()
})
.get('/health', () => {
return {
status: 'ok',
lastHandlerMs: lastRequestMs
? Math.round(performance.now() - lastRequestMs)
: null,
timestamp: new Date().toISOString(),
}
})
This is optional but surfacing lastHandlerMs in your health payload lets you set a Vigilmon response time alert — get notified if your API slows past an SLA threshold even while technically returning 200.
Step 3: Deploy Your Elysia App
Your app needs a public URL before Vigilmon can poll it.
Fly.io works great with Bun:
# fly.toml
app = "my-elysia-app"
primary_region = "iad"
[http_service]
internal_port = 3000
force_https = true
[[vm]]
memory = "256mb"
cpu_kind = "shared"
cpus = 1
fly launch --no-deploy
fly deploy
Railway and Render also support Bun out of the box — set the start command to bun run src/index.ts and they handle the rest.
Note your production health URL: https://my-elysia-app.fly.dev/health
Step 4: Create a Vigilmon HTTP Monitor
- Log in at vigilmon.online and click Add Monitor → HTTP.
- Fill in the monitor settings:
| Field | Value |
|---|---|
| URL | https://my-elysia-app.fly.dev/health |
| Method | GET |
| Check interval | 60 seconds |
| Expected status | 200 |
| Timeout | 10 seconds |
| Regions | Select 2–3 for triangulation |
-
Under Advanced, enable a JSON body assertion:
- Path:
status - Expected value:
ok
- Path:
-
Click Save.
Vigilmon begins polling immediately. Within 90 seconds you'll see the first green tick on your dashboard. The JSON body assertion means Vigilmon alerts you even if your endpoint returns 200 with "status": "degraded" — which happens when a dependency is broken but your server is still running.
Step 5: Add a Keyword Monitor for Your Frontend
If your Elysia app serves HTML pages (using Elysia's html plugin), add a second monitor:
- Add Monitor → HTTP
- URL:
https://my-elysia-app.fly.dev/ - Expected status:
200 - Keyword check: must contain a string unique to your app (e.g., your app name or a copyright string)
This catches the scenario where a CDN or proxy serves a cached error page with a 200 status — a plain HTTP status check would miss it entirely.
Step 6: Configure Alert Channels
Go to Alert Channels → Add channel.
Add your on-call email address. Vigilmon sends alerts on:
- Non-2xx HTTP status from any polled region
- JSON body assertion failure
- Response timeout exceeded
Slack Webhook
- Create a Slack Incoming Webhook in your workspace.
- In Vigilmon: Alert Channels → Add → Webhook, paste the URL, save.
- Assign the webhook channel to your monitors.
When the monitor fires you'll see:
🔴 my-elysia-app /health is DOWN
Status: 503 | Checked at: 2025-06-30 10:31 UTC
And when it recovers:
🟢 my-elysia-app /health is back UP (was down 3m 12s)
Step 7: Test the Alert Pipeline
Force a failure to verify alerts flow end-to-end before you need them at 2 AM:
// Temporarily override the health route
app.get('/health', () =>
new Response(JSON.stringify({ status: 'degraded', checks: { database: 'simulated error' } }), {
status: 503,
headers: { 'Content-Type': 'application/json' },
})
)
Deploy, wait one check interval (≤ 60s), and confirm the Slack/email notification arrives. Revert and confirm the recovery alert.
Production Checklist
- [ ]
/healthchecks all real dependencies (DB, cache, upstream APIs) - [ ] Unhealthy checks return
503, not200 - [ ] JSON body assertion enabled in Vigilmon
- [ ] Alert channels tested end-to-end before your first production incident
- [ ] Maintenance window configured for deployments to mute false alerts
Wrapping Up
Elysia's speed means you'll ship fast — monitoring with Vigilmon means you'll catch the breakages just as fast. You now have:
- A health endpoint that reflects real app state
- Vigilmon polling every 60 seconds from multiple regions
- Slack and email alerts the moment something breaks
Sign up for Vigilmon free — no credit card required, first 5 monitors included.
Building something with Elysia? Drop your stack in the comments.