Divergences from the original decisions
Where the shipped system departs from the decision record, why, and what it costs you.
TimescaleDB is not used
The decision record specified PostgreSQL 16 with TimescaleDB. Usage events are stored in plain PostgreSQL tables with composite time indexes instead. At the specified scale this answers every dashboard query comfortably, and it keeps managed PostgreSQL offerings viable.
If event volume grows an order of magnitude, TimescaleDB can be added additively (CREATE EXTENSION plus converting the usage-event table to a hypertable); every usage query is isolated in one store file.
Redis is not used
Sessions, OIDC sign-in state, and quota ledgers live in PostgreSQL; credentials are cached per replica in process memory for 60 seconds. This removes a stateful service from the operational surface.
Three consequences to know. First, quota enforcement reads the database ledger: concurrent requests can each pass an almost-exhausted check, so a cap can be overshot by the amount in flight; the reconciliation job trues the ledger up. Second, revoking an API token or a service token, or moving its expiry into the past, takes effect immediately on every replica: the 60-second credential cache only saves the digest lookup, and each cached hit re-reads the token row. Third, requests-per-minute rate-limit buckets live in process memory per replica, but each replica divides the limit by the number of live replicas, so the configured rate holds across the cluster. For up to 45 seconds after a replica stops, the survivors still divide by the old count and admit slightly less than the limit.
OTLP export is built in, not the OTel SDK
The decision record called for OpenTelemetry export via the OTel Go SDK. Janus ships a dependency-free OTLP/HTTP exporter instead: when OTEL_EXPORTER_OTLP_ENDPOINT is set, each proxied request produces a root span with quota-check, upstream-call, and usage-write children, and metric snapshots are exported on a configurable interval (default 30s). Export is strictly non-blocking — an unreachable collector yields a rate-limited warning log and nothing else — and the otel_enabled feature flag pauses it at runtime.
The exporter speaks OTLP/HTTP with the JSON encoding, so point the endpoint at a collector’s 4318 port, not the gRPC 4317 one. Without the environment variable there is no export at all; Prometheus /metrics remains the primary surface.
SQLite and dev-auth were added
Two evaluation conveniences exist that the decision record never asked for: an embedded SQLite backend (JANUS_DATABASE_URL=sqlite://…) and a no-IdP sign-in mode (JANUS_DEV_AUTH=true).
Dev-auth is off by default, requires an explicit opt-in, and logs a startup warning — but it accepts any email address without a password. Never enable it, or SQLite, on a deployment anyone else can reach. Startup enforces this: the process refuses to boot with dev-auth when JANUS_ENV=production or when JANUS_PUBLIC_URL is not loopback/localhost, unless JANUS_DEV_AUTH_ALLOW_UNSAFE=true explicitly overrides it for an isolated demo. Production remains PostgreSQL plus a real identity provider, exactly as specified.
URL path shapes differ from the requirement text
The requirement text named /api/v1/* as an OpenAI-compatible proxy path and placed admin endpoints under /admin/v1/*. The shipped routing uses a single canonical proxy namespace instead: the OpenAI-compatible surface is PUBLIC_URL/v1/* (this is the base URL to configure in SDKs), the first-party application API is /api/v1/*, and admin endpoints live at /api/v1/admin/* where they share the app API session auth and CSRF protection.
A client that follows the requirement text literally and points an SDK at PUBLIC_URL/api/v1 will reach the application API and get 404/401 JSON errors, not proxy responses. Always use PUBLIC_URL/v1 as the SDK base URL — the /api/v1/me response and the in-app help snippets report exactly this value.