ObjectStackObjectStack

Production Readiness

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.

ConcernDefaultDeep dive
Security response headers (CSP / XCTO / X-Frame-Options / …)OnHARDENING.md
HSTSOff (opt-in once TLS is confirmed)HARDENING.md
Rate limiting (token bucket)Off (opt-in via adapter)HARDENING.md
CSRFAdapter-layer (bearer-auth = N/A)HARDENING.md
Auth / session / JWT lifecycleOn via @objectstack/plugin-auth (better-auth)HARDENING.md
Metrics (counter / histogram / gauge)Noop (no adapter)OBSERVABILITY.md
Error reporting (5xx only)Noop (no adapter)OBSERVABILITY.md
Request id (X-Request-Id)Auto-generated when enabledOBSERVABILITY.md
W3C Trace Context (traceparent)Parser exported; SDK wiring is host's jobOBSERVABILITY.md

Wiring everything together

A typical production server enables all four:

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.

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.
  • Multi-org deployments: tenant isolation is active, not degraded — confirm features.degradedTenancy is false in /auth/config. A deployment requesting multi-org without @objectstack/organizations now refuses to boot unless OS_ALLOW_DEGRADED_TENANCY=1; never set that flag in production. See Tenancy Modes & Membership.
  • Backup / restore drill documented and tested.
  • Data-retention windows reviewed (ADR-0057): the platform's default lifecycle declarations bound telemetry (activity 14d, job runs 30d, notifications 90d, audit 90d-hot); extend per environment/tenant via the lifecycle.retention_overrides setting before go-live if your compliance regime needs longer, and register an archive datasource if audit data must move to cold storage instead of being retained hot.

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. @objectstack/plugin-audit writes sys_audit_log records via ObjectQL afterInsert/afterUpdate/afterDelete hooks; durable storage and tamper-evidence are the host's choice (append-only S3, immudb, etc.).

On this page