HyperRoute

Configuration Reference

Complete reference for router.yaml. Generated from routerd init.

All sections are optional — sensible defaults are applied automatically. The router operates in federation mode: subgraph URLs, schemas, and routing rules come from the supergraph bundle pushed via the control plane, not from this file. This file controls router-level behavior only.


Generated Default

Run routerd init to generate a production-ready router.yaml:

# HyperRoute Router Configuration
# ================================
#
# The router operates in push-based mode:
# - Router starts empty (no schema loaded)
# - Push snapshots via: POST /control-plane/snapshots
# - Activate snapshots via: POST /control-plane/activate
#
# Environment variables:
#   RUST_LOG                        - Log level (debug, info, warn, error)
#   LOG_FORMAT                      - Log format (json, pretty)
#   OTEL_EXPORTER_OTLP_ENDPOINT    - OTLP collector (e.g., http://localhost:4317)
#   OTEL_SERVICE_NAME              - Service name in traces (default: hyperroute-router)

mode: federation
server:
  host: 0.0.0.0
  port: 4000

Everything below the server block is optional. If omitted, the defaults documented here apply.


Top-Level Keys

KeyTypeDefaultDescription
modestringfederationAlways federation. Bundle-driven routing.
schemaobjectnullGraphQL SDL location. Optional when using bundles.
serverobjectrequiredHTTP server bind settings
limitsobjectdefaults belowConcurrency and dedup limits
persisted_opsobjectdisabledPersisted (allowlisted) operations
federationobjectdefaults belowEntity batching and plan cache
multi_tenantobjectdisabledMulti-tenant isolation
authobjectdisabledAuthentication and authorization
shutdownobjectdefaults belowGraceful shutdown behavior
securityobjectdefaults belowQuery validation and introspection
observabilityobjectdefaults belowMetrics, tracing, logs, slow queries
subscriptionsobjectdisabledReal-time subscriptions (SSE / graphql-ws)
http2objectenabledHTTP/2 upstream connection pool
pollobjectdisabled@poll directive for stateless real-time
pii_detectionobjectdisabledPII detection and masking
time_travelobjectdisabledTime Travel debugging
schema_rate_limitobjectdisabledField-level rate limiting
connection_affinityobjectdisabledUpstream connection affinity
n_plus_one_preventionobjectenabledN+1 query auto-prevention

server

server:
  host: 0.0.0.0
  port: 4000
FieldTypeDefaultDescription
hoststring0.0.0.0Bind address
portu164000HTTP listen port. Override with PORT env var.

limits

limits:
  max_concurrency_per_upstream: 100
  max_total_concurrency: 500
  max_inflight_fetches: 10000
  max_waiters_per_fetch: 1000
FieldTypeDefaultDescription
max_concurrency_per_upstreamusize100Semaphore per upstream
max_total_concurrencyusize500Global semaphore across all upstreams
max_inflight_fetchesusize10000Max in-flight dedup entries. 0 disables dedup.
max_waiters_per_fetchusize1000Max waiters coalesced on a single fetch

persisted_ops

persisted_ops:
  enabled: false
  allowlist_path: null
  mode: disabled
FieldTypeDefaultDescription
enabledboolfalseEnable persisted operations
allowlist_pathstringnullPath to JSON allowlist file
modestringdisabledenforce — block unknown ops. observe — log unknown. disabled — allow all.

federation

federation:
  entity_batching:
    enabled: false
    max_entities_per_batch: 200
    max_batch_wait_micros: 500
    max_entity_cache_entries: 2000
  plan_cache_capacity: 0
FieldTypeDefaultDescription
plan_cache_capacityusize0LRU cache slots for query plans. 0 = unbounded.

federation.entity_batching

FieldTypeDefaultDescription
enabledboolfalseEnable entity batching
max_entities_per_batchusize200Batch fires at this size
max_batch_wait_microsu64500Max wait before batch fires
max_entity_cache_entriesusize2000Per-request entity result cache

multi_tenant

multi_tenant:
  enabled: false
  resolution_strategy: header
  default_tenant: default
  header_name: x-tenant-id
  jwt_claim_path: tenant_id
  default_limits:
    max_qps: 1000
    max_concurrent_requests: 100
    max_subscriptions: 50
    max_cache_entries: 10000
  tenants: {}
FieldTypeDefaultDescription
enabledboolfalseEnable multi-tenant isolation
resolution_strategystringheaderheader, jwt, or api_key
default_tenantstringdefaultFallback tenant ID
header_namestringx-tenant-idTenant header (when strategy = header)
jwt_claim_pathstringtenant_idJWT claim for tenant (when strategy = jwt)
tenantsmap{}Per-tenant limit overrides

multi_tenant.default_limits

FieldTypeDefaultDescription
max_qpsu641000Max queries per second
max_concurrent_requestsu64100Max concurrent requests
max_subscriptionsu6450Max active subscriptions
max_cache_entriesu6410000Max cache entries

auth

auth:
  enabled: false
  strategy: jwt
  jwt:
    secret: null
    algorithm: HS256
    issuer: null
    audience: null
    required_claims: []
    tenant_claim: tenant_id
    roles_claim: roles
  api_key:
    header_name: x-api-key
    keys: []
  authorization:
    enabled: false
    rules: []
FieldTypeDefaultDescription
enabledboolfalseEnable authentication
strategystringjwtjwt or api_key

auth.jwt

FieldTypeDefaultDescription
secretstringnullHMAC secret or public key. Supports ${ENV_VAR}
algorithmstringHS256HS256, RS256, ES256, etc.
issuerstringnullExpected iss claim
audiencestringnullExpected aud claim
required_claimsstring[][]Claims that must be present
tenant_claimstringtenant_idClaim used for tenant resolution
roles_claimstringrolesClaim used for role-based auth

auth.api_key

FieldTypeDefaultDescription
header_namestringx-api-keyHeader containing the API key
keysstring[][]Allowed API keys

auth.authorization

FieldTypeDefaultDescription
enabledboolfalseEnable authorization rules
rulesarray[]Authorization rules

shutdown

shutdown:
  drain_timeout_secs: 30
  force_shutdown_after_secs: 35
  log_active_requests: true
FieldTypeDefaultDescription
drain_timeout_secsu6430Grace period for in-flight requests
force_shutdown_after_secsu6435Hard kill after drain
log_active_requestsbooltrueLog active requests during drain

security

security:
  max_query_depth: 15
  max_query_complexity: 5000
  max_query_length: 500000
  max_aliases_per_field: 15
  enable_introspection: false
  allow_argument_sampling: false
  allow_variable_logging: false
  redact_headers:
    - authorization
    - cookie
    - x-api-key
  log_body: false
FieldTypeDefaultDescription
max_query_depthusize15Maximum query nesting depth
max_query_complexityusize5000Maximum complexity score
max_query_lengthusize500000Maximum query string (bytes)
max_aliases_per_fieldusize15Maximum aliases per field
enable_introspectionboolfalseAllow introspection queries
allow_argument_samplingboolfalseSample query arguments in traces
allow_variable_loggingboolfalseLog query variables
redact_headersstring[][authorization, cookie, x-api-key]Headers redacted from logs
log_bodyboolfalseLog request/response bodies

observability

observability.metrics

observability:
  metrics:
    enabled: true
    listen_host: 0.0.0.0
    listen_port: 9091
    path: /metrics
    buckets_ms:
      - 1.0
      - 2.0
      - 5.0
      - 10.0
      - 25.0
      - 50.0
      - 100.0
      - 250.0
      - 500.0
      - 1000.0
      - 2500.0
      - 5000.0
    label_op_name: true
    max_ops_tracked: 2000
FieldTypeDefaultDescription
enabledbooltrueEnable Prometheus metrics export
listen_hoststring0.0.0.0Metrics server bind address
listen_portu169091Metrics server port
pathstring/metricsScrape endpoint path
buckets_msf64[][1, 2, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000]Histogram buckets (ms)
label_op_namebooltrueAdd operation name label to metrics
max_ops_trackedusize2000Max unique operations tracked (prevents cardinality explosion)

observability.tracing

  tracing:
    enabled: false
    otlp_endpoint: null
    service_name: hyperroute-router
    sampling_rate: 1.0
    propagation: w3c
FieldTypeDefaultDescription
enabledboolfalseEnable OTLP trace export
otlp_endpointstringnullOTLP gRPC endpoint. Override with OTEL_EXPORTER_OTLP_ENDPOINT env var.
service_namestringhyperroute-routerService name in traces. Override with OTEL_SERVICE_NAME.
sampling_ratef641.0Trace sampling rate (0.0–1.0)
propagationstringw3cContext propagation: w3c, b3, or jaeger

observability.slow_queries

  slow_queries:
    enabled: true
    threshold_ms: 250
    sample_rate: 1.0
    store_last_n: 5000
    include_plan: true
FieldTypeDefaultDescription
enabledbooltrueEnable slow query tracking
threshold_msu64250Queries slower than this are flagged
sample_ratef641.0Sampling rate for slow query capture
store_last_nusize5000Ring buffer of recent slow queries
include_planbooltrueInclude query plan in slow query data

observability.logs

  logs:
    structured: true
    slow_query_event: true
FieldTypeDefaultDescription
structuredbooltrueUse structured JSON logging
slow_query_eventbooltrueEmit log events for slow queries

observability.execution_intelligence

  execution_intelligence:
    enabled: true
    sampling_rate: 1.0
    include_in_response: false
    subgraph_spans: true
    entity_spans: true
FieldTypeDefaultDescription
enabledbooltrueEnable execution intelligence spans
sampling_ratef641.0Span sampling rate
include_in_responseboolfalseInclude execution details in GraphQL response extensions
subgraph_spansbooltrueEmit per-subgraph spans
entity_spansbooltrueEmit per-entity spans

subscriptions

subscriptions:
  enabled: false
  client_transport: sse
  sse:
    path: /graphql/stream
    heartbeat_interval_ms: 15000
    max_event_bytes: 262144
  upstream_ws:
    protocol: graphql-ws
    connect_timeout_ms: 5000
    keepalive_interval_ms: 15000
    reconnect:
      min_backoff_ms: 200
      max_backoff_ms: 10000
      max_retries: 5
      jitter: true
  limits:
    max_active_total: 20000
    max_active_per_tenant: 2000
    max_active_per_ip: 200
    max_active_per_connection: 50
    max_pending_events_per_subscription: 200
    max_event_rate_per_subscription_per_sec: 50
FieldTypeDefaultDescription
enabledboolfalseEnable subscription support
client_transportstringssesse or graphql-ws

subscriptions.sse

FieldTypeDefaultDescription
pathstring/graphql/streamSSE endpoint path
heartbeat_interval_msu6415000Heartbeat interval
max_event_bytesusize262144Max event payload size (256 KB)

subscriptions.upstream_ws

FieldTypeDefaultDescription
protocolstringgraphql-wsWebSocket sub-protocol
connect_timeout_msu645000Connection timeout
keepalive_interval_msu6415000Ping/pong keepalive interval

subscriptions.upstream_ws.reconnect

FieldTypeDefaultDescription
min_backoff_msu64200Initial backoff delay
max_backoff_msu6410000Maximum backoff cap
max_retriesu325Max reconnect attempts
jitterbooltrueApply jitter to backoff

subscriptions.limits

FieldTypeDefaultDescription
max_active_totalusize20000Global subscription limit
max_active_per_tenantusize2000Per-tenant limit
max_active_per_ipusize200Per-IP limit
max_active_per_connectionusize50Per-connection limit
max_pending_events_per_subscriptionusize200Event backpressure buffer
max_event_rate_per_subscription_per_secu3250Max events/sec per subscription

http2

http2:
  enabled: true
  pool_max_idle_per_host: 100
  pool_idle_timeout_secs: 300
  tcp_keepalive_secs: 30
  initial_window_size: 1048560
  max_frame_size: 16384
  adaptive_window: true
  max_concurrent_streams: 1000
  connect_timeout_ms: 5000
  request_timeout_ms: 30000
  preconnect: true
FieldTypeDefaultDescription
enabledbooltrueEnable HTTP/2 for upstream connections
pool_max_idle_per_hostusize100Max idle connections per host
pool_idle_timeout_secsu64300Idle connection timeout
tcp_keepalive_secsu6430TCP keepalive interval
initial_window_sizeu321048560Initial HTTP/2 window size (~1 MB)
max_frame_sizeu3216384Max HTTP/2 frame size (16 KB)
adaptive_windowbooltrueAuto-tune window size
max_concurrent_streamsu321000Max concurrent streams per connection
connect_timeout_msu645000Connection establishment timeout
request_timeout_msu6430000Per-request timeout
preconnectbooltruePreconnect to known subgraphs on startup

poll

poll:
  enabled: false
  min_interval_secs: 1
  max_interval_secs: 300
  default_interval_secs: 5
  max_per_connection: 5
  max_global: 5000
FieldTypeDefaultDescription
enabledboolfalseEnable @poll directive
min_interval_secsu641Minimum poll interval (prevents abuse)
max_interval_secsu64300Maximum poll interval
default_interval_secsu645Default when client omits interval
max_per_connectionusize5Max poll streams per WebSocket connection
max_globalusize5000Global max poll streams

pii_detection

pii_detection:
  enabled: false
  default_action: mask
  hash_secret: ''
  patterns:
    - type: email
      action: mask
      mask_char: '*'
      visible_chars: 3
      require_scope: read:email
    - type: phone
      action: mask
      mask_char: '*'
      visible_chars: 4
      require_scope: read:pii
    - type: ssn
      action: redact
      mask_char: '*'
      visible_chars: 4
      require_scope: read:pii
    - type: credit_card
      action: mask
      mask_char: '*'
      visible_chars: 4
      require_scope: read:payment
  field_rules: []
  audit:
    enabled: false
    log_access: true
    log_masked: false
FieldTypeDefaultDescription
enabledboolfalseEnable PII detection and masking
default_actionstringmaskDefault action: mask, redact, hash, block, or log
hash_secretstring""HMAC-SHA256 secret for hash action. Supports ${ENV_VAR}.
field_rulesarray[]Per-field override rules

pii_detection.patterns[]

Built-in patterns detect common PII types. Each pattern can be overridden:

FieldTypeDescription
typestringPII type: email, phone, ssn, credit_card
actionstringmask, redact, hash, block, or log
mask_charstringCharacter used for masking
visible_charsusizeNumber of trailing characters left visible
require_scopestringOAuth scope required to see unmasked value

pii_detection.audit

FieldTypeDefaultDescription
enabledboolfalseEnable PII audit logging
log_accessbooltrueLog PII field access
log_maskedboolfalseLog masked values (for debugging)

time_travel

time_travel:
  enabled: false
  recording:
    enabled: false
    sample_rate: 0.1
    storage: memory
    storage_path: .hyperroute/time-travel
    retention_days: 30
    exclude_variables:
      - password
      - token
      - secret
    exclude_headers:
      - authorization
      - cookie
      - x-api-key
    max_response_size: 1048576
  replay:
    enabled: true
    max_concurrent: 10
    timeout_ms: 30000
ℹ️

In production, use storage: otel to export recordings via OpenTelemetry. The router does not own storage — your observability platform captures and stores the recordings.

FieldTypeDefaultDescription
enabledboolfalseEnable time travel debugging

time_travel.recording

FieldTypeDefaultDescription
enabledboolfalseEnable recording
sample_ratef640.1Sampling rate (10%)
storagestringmemorymemory for dev, otel for production
storage_pathstring.hyperroute/time-travelLocal storage path (memory mode)
retention_daysu3230Retention period
exclude_variablesstring[][password, token, secret]Variables stripped from recordings
exclude_headersstring[][authorization, cookie, x-api-key]Headers stripped from recordings
max_response_sizeusize1048576Max recorded response size (1 MB)

time_travel.replay

FieldTypeDefaultDescription
enabledbooltrueEnable replay
max_concurrentusize10Max concurrent replays
timeout_msu6430000Replay timeout

schema_rate_limit

schema_rate_limit:
  enabled: false
  field_limits: {}
  type_limits: {}
  depth_limits: []
  subgraph_limits: {}
  defaults:
    requests_per_minute: 1000
    requests_per_second: 100
    max_depth: 15
FieldTypeDefaultDescription
enabledboolfalseEnable schema-aware rate limiting
field_limitsmap{}Per-field limits ("Type.field" → rate config)
type_limitsmap{}Per-type limits
depth_limitsarray[]Depth-based limits
subgraph_limitsmap{}Per-subgraph limits

schema_rate_limit.defaults

FieldTypeDefaultDescription
requests_per_minuteu641000Default per-minute limit
requests_per_secondu64100Default per-second limit
max_depthusize15Default max depth

connection_affinity

connection_affinity:
  enabled: false
  strategies: {}
  health_check:
    interval_seconds: 30
    timeout_seconds: 5
    unhealthy_threshold: 3
    healthy_threshold: 2
    path: /health
  global:
    max_bindings: 100000
    pool_size_per_instance: 50
    connection_reuse: true
FieldTypeDefaultDescription
enabledboolfalseEnable affinity routing
strategiesmap{}Per-subgraph strategy: session, consistent_hash, round_robin, least_connections
ℹ️

Subgraph names in strategies reference subgraphs from the bundle, not from this file.

connection_affinity.health_check

FieldTypeDefaultDescription
interval_secondsu6430Health check interval
timeout_secondsu645Health check timeout
unhealthy_thresholdu323Failures before marking unhealthy
healthy_thresholdu322Successes before marking healthy
pathstring/healthHealth check endpoint path

connection_affinity.global

FieldTypeDefaultDescription
max_bindingsusize100000Max affinity bindings in memory
pool_size_per_instanceusize50Connection pool per upstream instance
connection_reusebooltrueReuse connections across requests

n_plus_one_prevention

n_plus_one_prevention:
  enabled: true
  max_batch_size: 100
  batch_window_ms: 5
  deduplication_enabled: true
  adaptive_batching: false
  max_retries: 2
  log_patterns: true
FieldTypeDefaultDescription
enabledbooltrueEnable N+1 auto-prevention (enabled by default)
max_batch_sizeusize100Maximum batch size
batch_window_msu645Batch collection window (ms)
deduplication_enabledbooltrueDeduplicate entities within batches
adaptive_batchingboolfalseLearn cardinality patterns over time
max_retriesu322Retry failed batches
log_patternsbooltrueLog detected N+1 patterns

Environment Variables

VariableOverridesDescription
RUST_LOGLog level (debug, info, warn, error)
LOG_FORMATLog format (json, pretty)
OTEL_EXPORTER_OTLP_ENDPOINTobservability.tracing.otlp_endpointOTLP collector endpoint
OTEL_SERVICE_NAMEobservability.tracing.service_nameService name in traces
PII_HMAC_SECRETpii_detection.hash_secretHMAC secret for PII hashing
PORTserver.portHTTP listen port
HOSTserver.hostBind address

All inject header values and hash_secret support ${ENV_VAR} expansion.