Skip to content

Defaults

Freezing the v1 contract freezes the defaults: changing one after v1.0 is a breaking change even though no field name moves. This page is the pre-1.0 review of every resolved default — each is a decision on record, not an accident of implementation order. Verdict for all: keep. See Configuration for the full field reference these defaults apply to.

DefaultValueRationale
auth.modedisabledPaired with the CLI’s loopback bind (below): the out-of-the-box gateway is private to the machine, so the quick start works without an IdP. Exposure requires the deliberate act of passing --host 0.0.0.0, and production configs set mode: required. Secure-by-default network posture instead of mandatory auth.
--host127.0.0.1The other half of the pair. Never widen this default.
server.allowedHostslocalhost set (only when unset)DNS-rebinding protection that matches the loopback default. An explicit allowlist replaces — never extends — the localhost seed.
server.maxBodyBytes1 MiBBounds memory per request. Deliberately conservative; workloads shipping large base64 content raise it knowingly.
auth.ema.tokenTtlSec600Short-lived minted tokens; refresh is cheap (the ID-JAG is re-presented).
auth.ema.tokenRateLimitPerMinute600Anti-amplification on the unauthenticated token endpoint.
issuer.jwksUri{issuer}/.well-known/jwks.jsonCommon convention; IdPs that differ (e.g. Okta org servers) set it explicitly. A guess, but a configurable one.
issuer.groupsClaimgroupsOkta’s name; Entra/Auth0 set their own.

See Security & governance for how these defaults fit the overall trust model.

DefaultValueRationale
upstream.protocolsessionThe deliberate divergence from the SDK’s own preference: only sessionful connections carry server-initiated traffic (sampling, elicitation, logging, progress) back through the gateway. auto is the opt-out, not the default.
routing.namespaceSeparator__Survives every namespace character; validation rejects ambiguous separators.
routing.pageSize200Large enough that most federations are one page; small enough to bound response size. Negative opts out.
upstream.cacheTtlMs30000A backstop only — list_changed notifications invalidate immediately; the TTL covers upstreams that never send them.
DefaultValueRationale
timeoutsconnect 5 s, request 60 s, streamIdle 120 sRequest 60 s accommodates slow tools; connect 5 s fails over quickly (multi-endpoint upstreams try the next replica within the same attempt).
circuitBreaker5 failures / 30 s half-openConventional values; also the endpoint pool’s cooldown, by design (one “retry the unhealthy thing after” knob).
rateLimit (global, per-upstream)noneThe gateway must never throttle by surprise; limits are an operator’s policy, opted into.
healthCheckabsent (passive)Active probing costs a connect per endpoint per interval; passive ejection + cooldown is free and correct. Opt in.
discovery.intervalMs30000Registry churn is minutes-scale; 30 s balances freshness against load on the source.
discovery.allowedAuthStrategies / allowedSecretRefsabsent (unrestricted)Compatibility with pre-hardening discovery deployments; restricting by default post-v1.0 would break them. The producer (fold-discovery) is the inverse — default-deny — because it shipped with the hardening. Set the gateway allowlists whenever the discovery source is not operated by the gateway’s operators — see Discovery & Kubernetes.
server.redisUrlunset (in-process state)Single instances need no infrastructure; fleets opt in. Redis outages fail open, bounded 500 ms per operation.
DefaultValueRationale
tracingabsent (propagation-only)First-party spans are opt-in; W3C trace propagation is always on and free.
tracing.sampleRatio1.0An operator who configures tracing wants the traces; parent-based, so callers’ sampling decisions are honored either way.
tracing.serviceNamefold
--log-level / --log-formatinfo / textHuman-first on a terminal; json for collectors.

Non-configurable behaviors reviewed alongside (bridged-session idle sweep at 5 minutes, SSE-header hang timeout 3 s, discovery document cap 4 MiB, JWKS fetch bounds) are implementation details, not contract — they may be tuned or made configurable in any release.

Every row above shipped as of v1.0.0 and is covered by the API stability contract alongside the config document’s field names and types: changing a default’s value is exactly as breaking as renaming a field, because it changes behavior for every deployment that didn’t set the field explicitly. That’s why each one earned an explicit rationale rather than being left as an accident of whatever the code happened to initialize to first — and why the verdict for all of them, going into the freeze, was to keep them exactly as they are.