Production Readiness
Use production readiness with the current published Askr packages.
@askrjs/askr0.0.59
How to use production readiness
Verify the locked published packages, tests, production renderer, generated routes, and deployment fallback in the same order CI uses.
- Import the published @askrjs/askr entrypoint.
- Keep production readiness configuration next to the component, route, or server composition root that owns it.
- Handle pending, unavailable, cancellation, and failure states, then verify the production path.
npm ci
npm run lint
npm run test
npm run build
npm run verify:staticGoal and architecture
Production hardening in Askr is mostly about wiring the hooks the server already exposes: `ServerAppOptions.probes` for health checks, `ServerAppOptions.onError` for a last-resort error handler, and `@askrjs/otel`'s `createTelemetry()` for tracing, rather than bolting on separate infrastructure. `createTelemetry()` is explicitly a bridge to whatever OpenTelemetry SDK you install — the package 'never installs an SDK, processor, backend, or exporter' — so you own the actual exporter configuration.
Implementation
Set `probes: { livez, readyz, startupz, targetz }` on `createServerApp` so your orchestrator (Kubernetes, a load balancer) can distinguish 'process is alive' from 'ready to take traffic'; each `ProbeHandler` returns a boolean, a custom `Response`, or void for a default response. Wrap request handling in `telemetry.span('askr.request', fields, work)` or use the narrower helpers (`.loader`, `.action`, `.apiOperation`, `.ssrRender`) so spans line up with Askr's own lifecycle events, and call `telemetry.extract`/`.inject` to propagate trace context across service boundaries. In front of the process, use `serve(app, { port, host, signals })` from `@askrjs/node`, which installs signal handlers for graceful shutdown by default unless you pass `signals: false`.
Failure states
An unhandled exception in a handler should hit `ServerAppOptions.onError(error, context)` and return a safe response — without it, an uncaught error can leak stack traces or internal details to the client, so treat a missing `onError` as a launch blocker, not a nice-to-have. A `readyz` probe that always returns `true` defeats the purpose — wire it to a real dependency check (database reachable, cache warm) so your orchestrator actually stops routing traffic during a bad deploy instead of load-balancing into a broken instance.
Verification
Load-test the probe endpoints themselves under contention to confirm they don't become a bottleneck or false-negative when the process is merely busy, not actually unhealthy. Kill the process mid-request in a staging environment and confirm `serve()`'s signal handling drains in-flight requests before closing, rather than dropping connections immediately. Verify a deliberately thrown error in a handler is caught by `onError` and produces the sanitized response you expect, not a stack trace.