DEV Community

Vigilmon
Vigilmon

Posted on

Cloudflare Workers Monitoring with Vigilmon: Edge Function Health Checks

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:

  1. Log into Vigilmon
  2. Create a new HTTP monitor
  3. URL: https://worker.yoursubdomain.workers.dev/ or your custom domain
  4. Check interval: 1 minute
  5. Assert: Status code 200
  6. 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 });
Enter fullscreen mode Exit fullscreen mode

}
};

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 });
Enter fullscreen mode Exit fullscreen mode

}
};
`

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)