---
title: Production Readiness
description: Security headers, rate limiting, observability, and the go-live checklist for ObjectStack runtimes.
---

# Production Readiness

`@objectstack/runtime` ships first-class primitives for the cross-cutting
concerns every production deployment needs: HTTP hardening, rate limiting,
metrics, error reporting, and request-id correlation. Everything is
pluggable — defaults are safe, opt-in is gradual, and the framework
takes no hard dependency on Prometheus / OTel / Sentry / Redis.

This guide is the high-level overview. For the full reference (header
defaults, adapter recipes, go-live checklist) follow the deep-dive links.

| Concern | Default | Deep dive |
| :--- | :--- | :--- |
| Security response headers (CSP / XCTO / X-Frame-Options / …) | **On** | [HARDENING.md](https://github.com/objectstack-ai/framework/blob/main/docs/HARDENING.md) |
| HSTS | Off (opt-in once TLS is confirmed) | HARDENING.md |
| Rate limiting (token bucket) | Off (opt-in via adapter) | HARDENING.md |
| CSRF | Adapter-layer (bearer-auth = N/A) | HARDENING.md |
| Auth / session / JWT lifecycle | On via `@objectstack/plugin-auth` (better-auth) | HARDENING.md |
| Metrics (counter / histogram / gauge) | Noop (no adapter) | [OBSERVABILITY.md](https://github.com/objectstack-ai/framework/blob/main/docs/OBSERVABILITY.md) |
| Error reporting (5xx only) | Noop (no adapter) | OBSERVABILITY.md |
| Request id (`X-Request-Id`) | Auto-generated when enabled | OBSERVABILITY.md |
| W3C Trace Context (`traceparent`) | Parser exported; SDK wiring is host's job | OBSERVABILITY.md |

## Wiring everything together

A typical production server enables all four:

```ts
import { createDispatcherPlugin } from '@objectstack/runtime';
import { promMetrics } from './adapters/prom-metrics.js';     // your code
import { sentryReporter } from './adapters/sentry.js';        // your code

const dispatcher = createDispatcherPlugin({
  // Hardening
  securityHeaders: {
    hsts: { maxAge: 31536000, includeSubDomains: true, preload: true },
    // CSP defaults to deny-all (API server). Override here if you serve
    // a SPA from the same origin.
  },

  // Observability
  observability: {
    metrics: promMetrics,
    errorReporter: sentryReporter,
  },
});
```

That's it — every route the dispatcher mounts now:

1. Sends conservative security headers.
2. Echoes `X-Request-Id` (honored from caller, or freshly minted).
3. Emits `http_requests_total{method,route,status}` and
   `http_request_duration_ms` metrics.
4. Reports 5xx exceptions to Sentry (or your reporter) with the
   request id attached.

Rate limiting is the one piece you wire at the adapter layer (Fastify
preHandler, Hono middleware, etc.) because that's where you have
reliable access to the caller's IP and authenticated identity. See
the [HARDENING.md recipes](https://github.com/objectstack-ai/framework/blob/main/docs/HARDENING.md#rate-limiting).

## Go-live checklist

- [ ] HSTS enabled (after TLS is confirmed and you accept the lock-in).
- [ ] CSP tuned for your serving topology (deny-all API, looser for
      SPA-on-same-origin).
- [ ] Rate limit configured at the adapter for `/auth/*`, write
      verbs, and read verbs (auth bucket should be ~10/min/IP).
- [ ] Metrics adapter wired; `/metrics` endpoint (Prom) or OTel
      exporter producing data; alerts wired for error rate + p95
      latency per route.
- [ ] Error reporter wired; synthetic 5xx test reaches Sentry /
      Datadog / Rollbar.
- [ ] Log records include `requestId` and cross-check with the
      response `X-Request-Id` header.
- [ ] better-auth session TTL / refresh / revoke verified (curl
      checklist in HARDENING.md).
- [ ] Cross-tenant negative tests in CI.
- [ ] Backup / restore drill documented and tested.

## What's NOT in the runtime (yet)

- **OTel context propagation.** We export `parseTraceparent` /
  `formatTraceparent` so the host can wire `traceparent` into its OTel
  SDK, but we don't bundle the SDK itself. The OTel API surface is
  large and host-specific (Node vs. edge vs. browser).
- **A Prometheus `/metrics` endpoint.** Adapters mount their own
  scrape endpoint after wiring the `MetricsRegistry`. We give you the
  recipe, not the endpoint, because TLS / auth / path conventions vary.
- **A built-in audit log immutability layer.** SecurityPlugin emits
  audit records via the kernel event bus; durable storage and
  tamper-evidence are the host's choice (append-only S3, immudb, etc.).
