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.
| Signal | Proves | Blind spot |
|---|---|---|
| Deno metrics | Errors, latency in dashboard | No external synthetic path |
| Origin API check | Backend up | Edge routing can still fail |
| External GET | Same HTTPS users hit | Cron 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 });
}
- Pick canonical host — the public hostname customers use (including if you use a custom domain on Deno Deploy).
- Expose GET /healthz and /readyz on that host.
- Timeout dependency checks inside
/readyz(2–3s). - curl from outside before any monitor.
- 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.
| Companion | Monitoring role |
|---|---|
| Cron + KV heartbeat | /readyz returns 503 if heartbeat stale |
| External GET | Primary StillOnline signal |
| Dashboard traces | Debug 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.
- Sign in at stillonline.tech/app.
- Add check — GET
https://your-app.deno.net/readyz, expect 200. - Label component "Deno edge" on status page.
- Enable one alert channel on Free.
- 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
- Deploy production with
/healthzand/readyz. - Activate custom domain TLS if used.
- curl both paths from outside your network.
- Break origin — confirm
/readyzreturns 503. - Register StillOnline on
/readyz. - Test alert channel you read during incidents.
- 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
- Health endpoint design: /health vs /ready
- Edge uptime monitoring on Cloudflare Workers
- API-only SaaS uptime checks
- Health check URL quickstart
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.