← Blog

How to monitor Deno Deploy services and edge functions

Your Deno Deploy dashboard shows green metrics, yet users in one region see 5xx errors. Built-in logs, traces, and metrics watch traffic inside the platform — not whether a synthetic GET from the public internet succeeds. Fix it with /healthz and /readyz on your production URL, then point StillOnline at the same HTTPS address customers use.

Quick answer

Deno Deploy observability is in-dashboard telemetry, not external uptime. StillOnline sends HTTP GET and checks status codes only. Add GET /healthz (liveness) and /readyz (readiness with 503 on dependency failure). Free: one URL, ~five-minute interval, status code only.

Deno Deploy runs TypeScript at the edge with Deno.serve. The platform auto-traces HTTP and fetch calls — useful for debugging, not a substitute for scheduled probes from outside. See edge uptime monitoring and health check quickstart.

1. Compare what to monitor on Deno Deploy vs your origin API

Three layers: L1 edge URL (Deno.serve on your production hostname), L2 dependencies (REST API, Deno KV), L3 Deno.cron jobs. Dashboard metrics cover L1 inside Deno; they do not curl your public URL from another region.

SignalProvesBlind spot
Deno metricsErrors, latency in dashboardNo external synthetic path
Origin API checkBackend upEdge routing can still fail
External GETSame HTTPS users hitCron health only via /readyz

Deno Deploy runs in six datacenter regions. Routing can send users through one region while your home-network curl hits another — asymmetric failures are why external checks matter. Cold starts are usually under 100ms but can spike during capacity events; a five-minute StillOnline cadence fits most indie SaaS without alert noise.

Do: register StillOnline on the canonical production URL. Do not: treat the Observability tab alone as uptime proof.

2. Design public health URL for Deno edge handlers

/healthz = liveness (process answers). /readyz = readiness (dependencies OK). Return 503 when a dependency fails; use Cache-Control: no-store. Skip auth — monitors send no Authorization header. Stay under ~2 seconds.

// Deno.serve sketch
if (url.pathname === "/healthz") return new Response("ok\n", { status: 200, headers });
if (url.pathname === "/readyz") {
  const ready = await pingOrigin();
  return new Response(ready ? "ready\n" : "down\n", { status: ready ? 200 : 503, headers });
}
  1. Pick canonical host — the public hostname customers use (including if you use a custom domain on Deno Deploy).
  2. Expose GET /healthz and /readyz on that host.
  3. Timeout dependency checks inside /readyz (2–3s).
  4. curl from outside before any monitor.
  5. Return 503 when origin is unreachable for users.

Do: monitor /readyz for product truth. Do not: return 200 with {"ok": false} on StillOnline Free.

TLS on custom domains provisions via Let's Encrypt automatically — probe the same hostname users see, not a preview deployment URL. When /readyz calls your origin API, use fetch with AbortSignal.timeout so a slow database does not hang the edge past StillOnline's ~2s tolerance. See health endpoint design for liveness vs readiness trade-offs.

3. Add Deno.cron companions without false greens

Deno.cron registers at module top level before Deno.serve(). Production timelines only; UTC schedules; invocation may slip ~1 minute. Handlers run at-least-once.

CompanionMonitoring role
Cron + KV heartbeat/readyz returns 503 if heartbeat stale
External GETPrimary StillOnline signal
Dashboard tracesDebug only — not uptime

Optional pattern: a cron job writes last_ok to Deno KV every five minutes; /readyz returns 503 if the timestamp is older than fifteen minutes. That maps "background pipeline stuck" to HTTP for StillOnline without exposing cron URLs publicly.

Do: top-level cron with UTC schedules and backoffSchedule for retries. Do not: register cron inside request handlers — Deploy discovers jobs only at deploy time from top-level code.

Separate origin host behind the edge? See API-only SaaS uptime checks for adding a second StillOnline URL on Pro or Ultimate.

4. Wire StillOnline checks and alert routing

StillOnline runs HTTP GET, updates a status page, alerts after two consecutive failures.

  1. Sign in at stillonline.tech/app.
  2. Add checkGET https://your-app.deno.net/readyz, expect 200.
  3. Label component "Deno edge" on status page.
  4. Enable one alert channel on Free.
  5. Wait 2–3 cycles (~10–15 min) before tuning.

Do: use the URL that means "product down." Do not: point at preview deployments.

When an alert fires: curl /readyz from a home network, open Deno Deploy Traces filtered by HTTP 5xx, verify custom-domain TLS has not expired, and ping the origin if /readyz depends on it. StillOnline debounces two consecutive failed probes before DOWN — on Free that is roughly ten minutes. Pro ($9/mo) and Ultimate ($29/mo) add more URLs and all three alert channels — pricing.

5. Verify monitoring before launch week

  1. Deploy production with /healthz and /readyz.
  2. Activate custom domain TLS if used.
  3. curl both paths from outside your network.
  4. Break origin — confirm /readyz returns 503.
  5. Register StillOnline on /readyz.
  6. Test alert channel you read during incidents.
  7. Write runbook — metrics + curl + origin owner.

Do: rehearse 503 in staging by breaking the origin fetch while /healthz stays 200. Do not: launch without external probe — dashboard metrics can look healthy while a single region routes to a broken revision.

Compare with Cloudflare Workers: both platforms need external GET; Deno adds first-party Deno.cron and an OpenTelemetry dashboard. StillOnline connects identically — scheduled HTTP GET, status code evaluation, public status page.

What's next

Ship probes, curl from outside, register StillOnline on /readyz. Add cron-to-KV heartbeat if jobs gate user value.

Open the StillOnline dashboard and paste your Deno /readyz URL.

Related guides

FAQ

How does Deno Deploy monitoring compare to Cloudflare Workers with StillOnline?

Both need external HTTP GET. Deno adds Deno.cron and OpenTelemetry dashboard; StillOnline wiring is identical on either platform.

Should StillOnline monitor deno.net subdomain or custom domain?

The hostname customers use. Keep a second *.deno.net check on Pro as deploy smoke if needed.

Why are Deno metrics green while users see errors?

Regional routing or origin failures. External GET on /readyz plus Traces for 5xx narrows it down.

Should /readyz call Deno KV or origin API?

Only dependencies that block user traffic, with fast timeouts.

Does StillOnline Free parse JSON health bodies?

No. Status codes only — return 503 when unhealthy.

Can Deno.cron replace StillOnline external monitoring?

No. Cron runs inside the platform. Use it to feed /readyz; StillOnline stays the primary external probe.