How to Monitor Your Fresh (Deno) Application with Vigilmon
Fresh is Deno's full-stack web framework — built for the edge, with islands architecture, zero JS by default, and server-side rendering. This guide shows how to add health monitoring to your Fresh app and hook it up to Vigilmon for external uptime checks.
Adding a Health Route to Fresh
Fresh uses file-based routing. Create a health endpoint in your routes/ directory:
Basic Health Endpoint
// routes/health.ts
import { FreshContext, Handlers } from '$fresh/server.ts';
export const handler: Handlers = {
GET(_req: Request, _ctx: FreshContext) {
const health = {
status: 'ok',
framework: 'fresh',
runtime: 'deno',
version: Deno.version.deno,
timestamp: new Date().toISOString(),
};
return new Response(JSON.stringify(health), {
status: 200,
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'no-cache, no-store',
},
});
},
};
Health Check with KV Database
Fresh apps often use Deno KV. Include a connectivity check:
// routes/health.ts
import { FreshContext, Handlers } from '$fresh/server.ts';
export const handler: Handlers = {
async GET(_req: Request, _ctx: FreshContext) {
let kvStatus = 'unknown';
try {
const kv = await Deno.openKv();
await kv.get(['health_check']);
kvStatus = 'connected';
kv.close();
} catch (_err) {
kvStatus = 'error';
}
const isHealthy = kvStatus === 'connected';
return new Response(
JSON.stringify({
status: isHealthy ? 'ok' : 'degraded',
kv: kvStatus,
timestamp: new Date().toISOString(),
}),
{
status: isHealthy ? 200 : 503,
headers: { 'Content-Type': 'application/json' },
}
);
},
};
Deep Health Check (API Route)
// routes/api/health.ts
import { FreshContext, Handlers } from '$fresh/server.ts';
interface HealthCheck {
name: string;
status: 'pass' | 'fail';
latencyMs?: number;
}
export const handler: Handlers = {
async GET(_req: Request, _ctx: FreshContext) {
const startTime = Date.now();
const checks: HealthCheck[] = [];
// Check 1: KV store
try {
const kvStart = Date.now();
const kv = await Deno.openKv();
await kv.get(['ping']);
kv.close();
checks.push({ name: 'kv', status: 'pass', latencyMs: Date.now() - kvStart });
} catch {
checks.push({ name: 'kv', status: 'fail' });
}
// Check 2: External API (if you depend on one)
// try {
// const apiStart = Date.now();
// const res = await fetch('https://api.your-service.com/ping');
// checks.push({ name: 'external-api', status: res.ok ? 'pass' : 'fail', latencyMs: Date.now() - apiStart });
// } catch {
// checks.push({ name: 'external-api', status: 'fail' });
// }
const allPassing = checks.every(c => c.status === 'pass');
return new Response(
JSON.stringify({
status: allPassing ? 'ok' : 'degraded',
checks,
totalLatencyMs: Date.now() - startTime,
timestamp: new Date().toISOString(),
}),
{
status: allPassing ? 200 : 503,
headers: { 'Content-Type': 'application/json' },
}
);
},
};
Heartbeat for Fresh Background Tasks
If you're using Deno.cron in your Fresh app:
// utils/cron.ts
const HEARTBEAT = 'https://vigilmon.online/api/heartbeat/YOUR_MONITOR_ID';
Deno.cron('Cleanup', '0 3 * * *', async () => {
const kv = await Deno.openKv();
try {
// Your cleanup logic
await cleanupExpiredSessions(kv);
// Send heartbeat on success
await fetch(HEARTBEAT, { method: 'POST' });
} catch (err) {
console.error('Cron job failed:', err);
} finally {
kv.close();
}
});
Deploying Fresh on Deno Deploy
Deno Deploy runs Fresh at the edge. Monitor your deployed app:
- Your health endpoint is at:
https://your-app.deno.dev/health - Add this URL to Vigilmon
- Vigilmon checks from multiple regions
If your Fresh app is on a custom domain:
- Monitor:
https://yourdomain.com/health - SSL monitor:
https://yourdomain.com
Setting Up Vigilmon for Fresh
- Sign up at vigilmon.online
-
Add HTTP monitor →
https://your-fresh-app.deno.dev/health - Set interval: 1 min or 5 min
- Add SSL monitor if on custom domain
- Configure alerts: email + Slack
Self-Hosted Fresh (with systemd)
[Unit]
Description=Fresh Deno Application
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/fresh-app
ExecStart=/usr/local/bin/deno run \n --allow-net \n --allow-env \n --allow-read \n --allow-write \n main.ts
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Monitoring Checklist for Fresh Apps
- [ ]
routes/health.tsreturning 200 with JSON - [ ] KV connectivity check in health endpoint
- [ ] Heartbeat monitors for Deno.cron jobs
- [ ] Uptime monitor on Vigilmon
- [ ] SSL certificate monitor
- [ ] Alert channels configured
Top comments (0)