tutorial

Monitoring Cloudflare Workers with Vigilmon: Health Checks, Cron Triggers & KV Probes

Production-grade uptime monitoring for Cloudflare Workers — health endpoints, Cron Trigger heartbeats, R2/KV health probes, and Vigilmon HTTP monitors.

Cloudflare Workers run at the edge in 300+ data centres worldwide. That distribution is a reliability advantage, but it also means failures are harder to spot: a Worker that errors in one region may still return 200 OK in your browser. Silent deployment failures, KV namespace misconfigurations, and upstream fetch timeouts all surface as degraded user experience rather than clean error pages. Vigilmon closes that gap — it pings your Worker's health endpoint from an external vantage point and alerts you the moment something breaks.

This tutorial walks through adding production-grade monitoring to a Cloudflare Workers application.

What You'll Build

  • A /health handler inside your Worker that checks KV and R2 connectivity
  • A Vigilmon HTTP monitor targeting your workers.dev domain
  • A Cron Trigger that acts as a heartbeat for scheduled Worker jobs
  • Alert channels (email + webhook) in Vigilmon

Prerequisites

  • A Cloudflare Workers project using Wrangler v3+
  • KV namespace or R2 bucket (optional — skip those checks if you don't use them)
  • A free account at vigilmon.online

Step 1: Add a Health Handler to Your Worker

Workers use a fetch handler as the entry point. Add a dedicated /health route that checks your real dependencies instead of just returning a static 200.

// src/index.ts
export interface Env {
  MY_KV: KVNamespace;
  MY_BUCKET: R2Bucket;
}

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

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

    // ... rest of your routing
    return new Response("Not found", { status: 404 });
  },
};

async function handleHealth(request: Request, env: Env): Promise<Response> {
  const checks: Record<string, string> = {};
  let ok = true;

  // KV probe — write then read a sentinel key
  try {
    const key = "__health_probe__";
    await env.MY_KV.put(key, "1", { expirationTtl: 60 });
    const val = await env.MY_KV.get(key);
    checks.kv = val === "1" ? "ok" : "read_mismatch";
    if (checks.kv !== "ok") ok = false;
  } catch (err) {
    checks.kv = `error: ${(err as Error).message}`;
    ok = false;
  }

  // R2 probe — head a known object (skip if not using R2)
  try {
    const obj = await env.MY_BUCKET.head("_probe");
    checks.r2 = obj !== null ? "ok" : "probe_object_missing";
    // A missing probe object is a config warning, not a hard failure
  } catch (err) {
    checks.r2 = `error: ${(err as Error).message}`;
    ok = false;
  }

  // Upstream fetch probe — replace with your real dependency
  try {
    const resp = await fetch("https://api.example.com/ping", {
      signal: AbortSignal.timeout(3000),
    });
    checks.upstream = resp.ok ? "ok" : `http_${resp.status}`;
    if (!resp.ok) ok = false;
  } catch (err) {
    checks.upstream = `error: ${(err as Error).message}`;
    ok = false;
  }

  return Response.json(
    { status: ok ? "ok" : "degraded", checks },
    { status: ok ? 200 : 503 }
  );
}

Deploy with wrangler deploy. Your health endpoint will be available at:

https://<worker-name>.<account>.workers.dev/health

Step 2: Add Vigilmon HTTP Monitor

  1. Log in to Vigilmon and click Add Monitor → HTTP.
  2. Set URL to https://<your-worker>.workers.dev/health.
  3. Set Check interval to 60 seconds (Workers have no cold-start penalty, so 60 s is appropriate).
  4. Set Expected status code to 200.
  5. Under Advanced, enable JSON body assertion and add:
    • Path: status
    • Expected value: ok
  6. Save. Vigilmon will now alert you any time your Worker returns non-200 or status != "ok".

Alert channels

Go to Alerts → Add channel and configure:

  • Email — your on-call address for immediate page-level alerts
  • Webhook — point it at a Slack incoming webhook or PagerDuty endpoint

Step 3: Cron Trigger Heartbeat for Scheduled Workers

If your Worker runs on a Cron Trigger (a scheduled job), a simple HTTP monitor won't catch it failing silently between runs. Instead, configure the Worker to ping Vigilmon's heartbeat URL at the end of each successful run.

wrangler.toml

[triggers]
crons = ["*/5 * * * *"]   # every 5 minutes

Scheduled handler

export default {
  // ... fetch handler above ...

  async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext) {
    try {
      await runYourJob(env);

      // Ping Vigilmon heartbeat — replace URL from your monitor's settings
      await fetch("https://vigilmon.online/api/heartbeat/<your-heartbeat-id>", {
        method: "POST",
      });
    } catch (err) {
      // Job failed — do NOT ping the heartbeat so Vigilmon fires an alert
      console.error("Scheduled job failed:", err);
    }
  },
};

In Vigilmon, create a Heartbeat monitor and set the grace period to slightly longer than your cron interval (e.g., 7 minutes for a 5-minute cron). If Vigilmon doesn't receive a ping within the grace period, you get an alert.


Step 4: Multi-Region Awareness

Workers are deployed globally, but a monitor from a single external probe location may not surface region-specific issues. Vigilmon's monitors run from multiple probe regions automatically. Review your monitor's Check log to see which region flagged an error — this helps you distinguish a global outage from a regional edge-cache issue.

If you use Cloudflare Access to protect internal routes, add your Vigilmon probe IPs to the Access bypass list, or create a separate unauthenticated /health route behind a secret token:

if (url.pathname === "/health") {
  const token = request.headers.get("X-Health-Token");
  if (token !== env.HEALTH_TOKEN) {
    return new Response("Unauthorized", { status: 401 });
  }
  return handleHealth(request, env);
}

In Vigilmon, set a Custom header: X-Health-Token: <value> in the monitor settings.


Step 5: Status Page

Vigilmon generates a public status page for your monitors. Go to Status Pages → Create, add your Worker monitor, and embed the badge in your README or documentation:

<img src="https://vigilmon.online/badge/<monitor-id>.svg" alt="API Status" />

Visitors see real-time uptime without you having to maintain a separate status page.


What You Get

| Scenario | How Vigilmon catches it | |---|---| | Worker throws an unhandled exception | HTTP monitor sees 5xx, fires alert | | KV namespace loses write access | /health returns degraded, Vigilmon alerts | | Scheduled job silently hangs | Heartbeat not received in grace period | | Upstream API goes down | /health upstream check fails | | Deployment breaks a route | HTTP monitor on the affected URL fires alert |


Workers are fast and globally distributed, but they still fail. External monitoring from Vigilmon gives you the independent vantage point you can't get from Cloudflare's own analytics dashboard.

Set up monitoring for your Cloudflare Workers app today — register free at vigilmon.online.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →