Skip to content
Keel
All docs

Health checks & errors

Two small hooks for running Keel in production: a health endpoint for uptime monitors, and one place every uncaught server error passes through.

/api/health

app/api/health/route.ts runs select 1 against the database with a 3 second timeout and answers:

json
{ "status": "ok", "database": "ok", "latencyMs": 12 }

with a 200, or { "status": "down", "database": "down" } with a 503 when the query fails or times out. Point any uptime monitor at it and alert on anything that isn't a 200. It's public on purpose and never includes error messages, hostnames or versions, the real error goes to the server log. Responses are Cache-Control: no-store, so a CDN can't keep serving a stale "ok".

Server errors

Next calls onRequestError in instrumentation.ts for every uncaught error in a route handler, Server Component render or proxy.ts. Keel hands it to reportServerError in lib/observability.ts, which:

  • Logs one JSON line to stderr with the message, the error digest, the route and the method. The digest is the same "Reference" the error pages show, so a user's screenshot maps straight to a log line.
  • POSTs the same JSON to ERROR_REPORT_WEBHOOK_URL when that's set (a log drain, an incident tool, your own collector), with a 3 second timeout. A failing webhook is logged and never throws.

Query strings and request headers are left out of every report, they can carry reset tokens, session cookies and API keys.

Using Sentry or OpenTelemetry?

Replace the body of reportServerError with your SDK's capture call and leave instrumentation.ts alone. Client-side errors still reach the error.tsx boundaries, which log to the browser console, add your SDK's browser capture there.