Cloudflare Workers Monitoring with Vigilmon: Edge Function Health Checks
Cloudflare Workers run at the edge — in 300+ data centers worldwide, milliseconds from your users. They're used for everything from API routing to full application backends. When a Worker fails, requests from your users silently return errors. Vigilmon monitors your Cloudflare Workers endpoints externally, giving you immediate alerts when edge functions break.
Why Cloudflare Workers Need External Monitoring
Workers can fail in ways that Cloudflare's own analytics can miss until it's too late:
- Deployment errors: A bad deploy can break a Worker for all users instantly
- CPU time limit exceeded: Workers have a 50ms CPU time limit (free) or 30s (paid); logic errors can hit this
- Memory limits: Workers are limited to 128MB; memory leaks fail silently
- External dependency failures: A Worker calling an external API that goes down will return errors
- KV store latency spikes: Cloudflare KV consistency issues can slow Workers significantly
- Script size limits: Approaching the 5MB compressed script limit can cause deployment failures
Vigilmon catches all of these by monitoring the HTTP response your Worker actually returns.
Setting Up Cloudflare Workers Monitoring
Option 1: Monitor Your Worker's URL Directly
The simplest approach — monitor the URL your Worker handles:
- Log into Vigilmon
- Create a new HTTP monitor
- URL: https://worker.yoursubdomain.workers.dev/ or your custom domain
- Check interval: 1 minute
- Assert: Status code 200
- Assert: Response time < 500ms (Workers should be fast)
Option 2: Add a Dedicated Health Route
Add a /health route to your Worker:
`javascript
// worker.js (modern Cloudflare Workers syntax)
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname === '/health') {
return handleHealth(request, env, ctx);
}
// ... your normal Worker logic
return new Response('Hello World', { status: 200 });
}
};
async function handleHealth(request, env, ctx) {
const checks = {};
const start = Date.now();
// Check KV store
if (env.MY_KV) {
try {
await env.MY_KV.put('health_check', 'ok', { expirationTtl: 60 });
const val = await env.MY_KV.get('health_check');
checks.kv = val === 'ok' ? 'healthy' : 'unhealthy';
} catch (e) {
checks.kv = 'unhealthy';
}
}
// Check D1 database
if (env.MY_DB) {
try {
const result = await env.MY_DB.prepare('SELECT 1 as ok').first();
checks.d1 = result?.ok === 1 ? 'healthy' : 'unhealthy';
} catch (e) {
checks.d1 = 'unhealthy';
}
}
// Check external dependency
try {
const response = await fetch('https://api.external-service.com/ping', {
signal: AbortSignal.timeout(3000)
});
checks.external_api = response.ok ? 'healthy' : 'degraded';
} catch (e) {
checks.external_api = 'unhealthy';
}
const allHealthy = !Object.values(checks).includes('unhealthy');
return Response.json({
status: allHealthy ? 'healthy' : 'unhealthy',
checks,
latency_ms: Date.now() - start,
colo: request.cf?.colo,
timestamp: new Date().toISOString()
}, { status: allHealthy ? 200 : 503 });
}
`
TypeScript Version
` ypescript
interface Env {
MY_KV: KVNamespace;
MY_DB: D1Database;
}
interface HealthStatus {
status: 'healthy' | 'unhealthy' | 'degraded';
checks: Record;
latency_ms: number;
timestamp: string;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise {
const url = new URL(request.url);
if (url.pathname === '/health') {
const start = Date.now();
const checks: Record<string, string> = {};
// Check KV
try {
await env.MY_KV.put('health', 'ok', { expirationTtl: 30 });
checks.kv = 'healthy';
} catch {
checks.kv = 'unhealthy';
}
const allHealthy = !Object.values(checks).includes('unhealthy');
const body: HealthStatus = {
status: allHealthy ? 'healthy' : 'unhealthy',
checks,
latency_ms: Date.now() - start,
timestamp: new Date().toISOString()
};
return Response.json(body, { status: allHealthy ? 200 : 503 });
}
return new Response('OK', { status: 200 });
}
};
`
Deploy with Wrangler
` oml
wrangler.toml
name = "my-worker"
main = "worker.js"
compatibility_date = "2024-09-01"
[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-namespace-id"
`
ash
wrangler deploy
Point Vigilmon at https://my-worker.your-subdomain.workers.dev/health.
Recommended Vigilmon Settings for Cloudflare Workers
| Setting | Value | Reason |
|---|---|---|
| Check interval | 1 minute | Edge deployments are instant |
| Confirmation failures | 1 | Workers should always be fast |
| Response timeout | 5s | Workers should respond in <100ms normally |
| Alert on slow response | >500ms | Indicates performance problems |
| SSL monitoring | Yes | Custom domains need cert monitoring |
Monitor Multiple Worker Environments
Workers has staging environments (.dev suffix, wrangler preview). Monitor both:
Production: https://your-worker.yourdomain.com/health
Staging: https://your-worker.your-subdomain.workers.dev/health
Create separate Vigilmon monitors for each environment to catch staging issues before they reach production.
Monitoring Workers with Cloudflare Analytics + Vigilmon
Cloudflare Analytics shows aggregate request/error metrics. Vigilmon provides:
- External, user-perspective availability data
- SSL certificate expiry alerts
- Public status pages for your users
- Alert routing to your team
The two are complementary: Cloudflare Analytics for aggregate trends, Vigilmon for real-time alerting.
Start monitoring your Cloudflare Workers for free at Vigilmon - external health checks in minutes.
Top comments (0)