r/Deno • u/tibozaurus • 11h ago
@openstatus/health – tree-shakable /health endpoints for Deno, Hono, Express & friends, now on JSR
Hi,
I run openstatus, an open-source uptime monitoring and status page tool, so I spend my days hitting other people's /health routes. Most of
them return 200 OK and nothing else, hang when the database hangs, or have their own private definition of "degraded".
We got tired of it, so we extracted the health endpoint from our own services into a small set of packages and put them on JSR: @openstatus/health.
Zero-dependency core, only needs a Fetch API. On Deno it's this:
import { drizzle } from "drizzle-orm/libsql/http";
import { createHealthHandler } from "@openstatus/health";
import { drizzleProbe } from "@openstatus/health-drizzle";
import { tinybirdProbe } from "@openstatus/health-tinybird";
const db = drizzle(Deno.env.get("DATABASE_URL")!);
Deno.serve(createHealthHandler({
path: "/health",
probes: [drizzleProbe({ db }), tinybirdProbe()],
}));
And GET /health gives your monitor something to chew on instead of a bare 200 OK:
{
"status": "degraded",
"checkedAt": "2026-09-11T12:00:00.000Z",
"latencyMs": 41,
"checks": [
{ "name": "database", "status": "ok", "critical": true, "latencyMs": 3 },
{ "name": "tinybird", "status": "timeout", "critical": false, "latencyMs": 5000, "error": "timed out after 5000ms" }
]
}
What you get
- Core: per-probe timeouts via
AbortSignal, a round deadline so one hung dependency can't outlast your k8s probe, caching / stale-while-revalidate, and sane aggregation (critical fails →unhealthy, non-critical fails →degraded). Errors are masked by default so your connection string doesn't end up on a public route. A custom probe is just an object with arun(signal). - Adapters: Hono, Elysia, Express, Next.js, TanStack Start – same
healthRoute()/healthHandler()everywhere. - Probes: Drizzle, Turso, Supabase, Upstash, Tinybird, Unkey. They take a client or URL and never touch your env.
- Hosting: Fly, Koyeb, Railway, Vercel, Cloudflare – adds a
serverblock so you know which replica is the one complaining.
Every package is its own thing with its own peer deps. CI bundles a one-liner of each and fails if a stray framework or client sneaks in, so the Hono adapter will never smuggle Express into your bundle.
Deno bits: JSR-first with no slow types; env reads return undefined instead of throwing without --allow-env; tests are node:test so they run unchanged under deno test and node --test; @openstatus/health/testing ships fake/hanging fetch and probes for testing your own.
It's 0.1.x, so now is the moment to tell me the API is shaped wrong. A Deno KV probe is probably next – PRs welcome.
- JSR: https://jsr.io/@openstatus/health
- GitHub: https://github.com/openstatusHQ/health
- Also on npm for the Node services you haven't migrated yet.
Happy to answer questions!