DEV Community

Vigilmon
Vigilmon

Posted on

How to Monitor Your Cloudflare Workers with Vigilmon

How to Monitor Your Cloudflare Workers with Vigilmon

Cloudflare Workers run your code at the edge — in 300+ data centers worldwide, milliseconds from your users. They're used for API proxies, authentication, A/B testing, bot protection, and full-stack apps via Workers + D1 + R2. But edge deployments introduce unique monitoring challenges.

This guide explains how to monitor your Cloudflare Workers effectively using Vigilmon.

Why Cloudflare Workers Need Monitoring

Cloudflare Workers are incredibly reliable — Cloudflare's network has 99.99%+ uptime. But your code running on that network can still fail:

  • Runtime errors: Unhandled exceptions crashing your Worker
  • CPU time limits: Workers have 10ms (free) / 50ms (paid) CPU time limits — exceeded limits return errors
  • Memory limits: Workers have a 128MB memory limit
  • KV/D1/R2 failures: Storage layer issues causing Worker failures
  • Deployment errors: A bad deploy pushed to production silently breaking requests
  • Route mismatches: New routes not matching expected patterns
  • Third-party API failures: Workers calling external APIs that go down

Setting Up a Health Endpoint in Your Worker

Add a dedicated health route to your Cloudflare Worker:

// worker.js
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    // Health check endpoint
    if (url.pathname === '/health') {
      return handleHealthCheck(env);
    }

    // Your normal routing...
    return handleRequest(request, env, ctx);
  }
};

async function handleHealthCheck(env) {
  const checks = {};
  const start = Date.now();

  // Check KV availability (if you use it)
  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' ? 'ok' : 'error';
    } catch (e) {
      checks.kv = 'error';
    }
  }

  // Check D1 (if you use it)
  if (env.MY_DB) {
    try {
      await env.MY_DB.prepare('SELECT 1').first();
      checks.d1 = 'ok';
    } catch (e) {
      checks.d1 = 'error';
    }
  }

  const allOk = Object.values(checks).every(s => s === 'ok');
  const latency = Date.now() - start;

  return Response.json({
    status: allOk ? 'ok' : 'degraded',
    latency_ms: latency,
    checks,
    region: request.cf?.colo || 'unknown'
  }, {
    status: allOk ? 200 : 503
  });
}
Enter fullscreen mode Exit fullscreen mode

TypeScript Version

// worker.ts
interface Env {
  MY_KV: KVNamespace;
  MY_DB: D1Database;
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);

    if (url.pathname === '/health') {
      return handleHealth(env, request);
    }

    return handleRequest(request, env, ctx);
  }
};

async function handleHealth(env: Env, request: Request): Promise<Response> {
  const start = performance.now();

  try {
    // Test your critical integrations
    await Promise.all([
      env.MY_KV.put('_hc', '1', { expirationTtl: 30 }),
      env.MY_DB.prepare('SELECT 1').first()
    ]);

    return Response.json({
      status: 'ok',
      latency_ms: Math.round(performance.now() - start),
      cf_datacenter: (request as any).cf?.colo
    });
  } catch (err) {
    return Response.json({
      status: 'error',
      error: err instanceof Error ? err.message : 'Unknown error'
    }, { status: 503 });
  }
}
Enter fullscreen mode Exit fullscreen mode

Monitoring with Wrangler Environments

For multi-environment setups (staging + production), create separate Vigilmon monitors for each:

# wrangler.toml
[env.staging]
route = "staging.example.com/*"

[env.production]
route = "example.com/*"
Enter fullscreen mode Exit fullscreen mode

In Vigilmon:

  • Monitor 1: https://staging.example.com/health — 2 min interval
  • Monitor 2: https://example.com/health — 1 min interval

Setting Up the Vigilmon Monitor

  1. Go to vigilmon.online and sign up free
  2. Add MonitorHTTP(S)
  3. URL: https://yourdomain.com/health
  4. Interval: 1 minute for production Workers
  5. Response validation:
    • Status: 200
    • Body contains: "status":"ok"
  6. Alert channels: Email + Slack webhook for production

Monitoring Cloudflare Workers Routes

If your Worker handles multiple critical routes, monitor them individually:

// Test your most critical routes
const criticalRoutes = [
  { path: '/api/v1/status', expectStatus: 200 },
  { path: '/api/v1/auth/verify', expectStatus: 401 }, // should return 401 without credentials
];
Enter fullscreen mode Exit fullscreen mode

In Vigilmon, add a monitor for each critical route with appropriate status code expectations.

Handling Cold Start Monitoring

Cloudflare Workers don't have traditional cold starts (they're always warm), but they do have initialization time for first requests to new PoPs. Your /health endpoint helps track this:

async function handleHealthCheck(env) {
  const {
    scriptVersion = 'unknown'
  } = globalThis.__CF_BUILD_INFO || {};

  return Response.json({
    status: 'ok',
    version: scriptVersion,
    timestamp: new Date().toISOString()
  });
}
Enter fullscreen mode Exit fullscreen mode

Monitor the response time with Vigilmon — a sustained increase suggests storage layer issues.

Summary

Cloudflare Workers are reliable, but your code and integrations (KV, D1, R2, external APIs) can still fail. With a proper health endpoint and Vigilmon monitoring:

  • Detect deployment failures within 60 seconds
  • Monitor storage integrations (KV, D1, R2) continuously
  • Track response times across Cloudflare's global network
  • Alert before users notice when something breaks

Start monitoring your edge functions for free at vigilmon.online.

Top comments (0)