Runtime configuration (:runtime)
The :runtime module reads its operational settings from the runtime.* block of application.yaml: the built-in HTTP server, Micrometer metrics, the /info and /config endpoint visibility, and the broker/Schema-Registry health checks. This page is a task-oriented walkthrough of that block. Two related top-level blocks — logging.* and the Kafka client passthrough under stoatflow.kafka.* — round out what you need to operate a runtime app.
runtime.* is the infrastructure half of the config. The engine half (lanes, commit barriers, state, watermarks) lives under stoatflow.* — see Core configuration. For the conceptual split, read Configuration model.Where runtime config comes from
StoatFlowRuntime.fromConfig(...) loads application.yaml from the classpath, layers environment variables on top, and starts the HTTP + metrics server before your topology. The runtime.* block is only consulted by the :runtime module — a :core-only application has no HTTP server, no metrics endpoint, and no runtime: block to configure.
Every runtime.* key maps to an environment variable using the same __-separated convention as the engine config: double underscore (__) is a path separator, single underscore is a word boundary (kebab-case). The first segment is the config root, and it must name the block being targeted — for runtime.* keys that root is runtime, so runtime.http.port becomes RUNTIME__HTTP__PORT. (Engine keys under stoatflow.* use the STOATFLOW__ root; logging levels use LOGGING__LEVEL__.) A variable that does not start with one of these three recognised roots is ignored — STOATFLOW__RUNTIME__HTTP__PORT would resolve to the nonexistent path stoatflow.runtime.http.port and silently fail to set the port. Environment variables take precedence over YAML — convenient for per-environment overrides without rebuilding the image.
The full runtime.* shape
Every key shown here is at its default value, so this block is equivalent to omitting runtime: entirely. Trim it down to just the keys you actually change.
runtime:
http:
enabled: true # serve the HTTP admin + metrics server
host: 0.0.0.0 # bind address (all interfaces)
port: 8080
backlog: 50 # max pending socket connections
debug:
enabled: true # register /debug/threads and /debug/barriers
metrics:
enabled: true # expose /metrics in Prometheus format
prefix: stoatflow # prefix for all metric names
recording-level: info # info | debug | trace
bind-jvm-metrics: true # JVM memory, GC, threads
common-tags: {} # tags applied to every metric
endpoints:
info:
show-app: true
show-java: true
show-kafka: true
show-uptime: true
show-state: true
show-watermarks: true
show-topology: true
show-endpoints: true
config:
enabled: true # serve the /config endpoint
health:
kafka-broker:
timeout-ms: 2000
schema-registry:
timeout-ms: 5000
HTTP server (runtime.http)
The runtime starts a JDK built-in HTTP server on a virtual-thread executor. It serves health probes, metrics, topology introspection, and the pause/unpause controls. See REST API for the full endpoint catalogue.
| Key | Default | Purpose |
|---|---|---|
runtime.http.enabled | true | Set false to run with no HTTP server at all. You lose health probes, /metrics, and the admin endpoints — only do this for an embedded/library use case. |
runtime.http.host | 0.0.0.0 | Bind address. 0.0.0.0 binds all interfaces (the right choice inside a container). Use 127.0.0.1 to restrict to loopback. |
runtime.http.port | 8080 | Listen port. |
runtime.http.backlog | 50 | Maximum pending connections in the socket backlog. |
runtime.http.debug.enabled | true | Registers /debug/threads and /debug/barriers. When false, both return 404. Disable to reduce attack surface on hardened deployments — there is no hot-path cost either way. |
A typical production override binds a fixed port and turns the debug endpoints off:
runtime:
http:
port: 8080
debug:
enabled: false
/debug/threads and /debug/barriers are pull-only snapshots used to diagnose a stuck commit pipeline. They are safe to leave on, but if your threat model limits what the admin port exposes, gating them with runtime.http.debug.enabled: false is the supported way to remove them. See REST API.Metrics (runtime.metrics)
Metrics are collected with Micrometer and exposed at /metrics in Prometheus text format. Scrape it from your existing monitoring stack — there is no agent to install. For the metric catalogue, see Metrics.
| Key | Default | Purpose |
|---|---|---|
runtime.metrics.enabled | true | Master switch for metric collection and the /metrics endpoint. |
runtime.metrics.prefix | stoatflow | Prefix applied to every metric name. Change it if your conventions require a different namespace. |
runtime.metrics.recording-level | info | Detail level: info (essential operational metrics, production-safe), debug (higher-cardinality troubleshooting metrics), trace (deep internals, development only). |
runtime.metrics.bind-jvm-metrics | true | Binds JVM memory, GC, and thread metrics into the registry. |
runtime.metrics.common-tags | {} | A map of tags applied to every metric — useful for environment, region, or service identification. |
Common tags are how you keep one Prometheus/Grafana setup readable across many deployments:
runtime:
metrics:
prefix: stoatflow
recording-level: info
common-tags:
env: production
region: eu-west-1
service: order-processor
Endpoint visibility (runtime.endpoints)
This block controls what the human-facing /info endpoint discloses and whether /config is served. It does not affect health, metrics, or topology endpoints.
/info fields
runtime.endpoints.info.* are individual booleans (all true by default) that include or omit a section from the /info JSON response:
| Key | Includes |
|---|---|
show-app | Application id |
show-java | Java runtime version and vendor |
show-kafka | Bootstrap servers |
show-uptime | Process uptime |
show-state | StoatFlow application state with transition history |
show-watermarks | Global and per-partition watermark state |
show-topology | Topology traits and active optimizations |
show-endpoints | The list of available HTTP endpoints |
/config endpoint
| Key | Default | Purpose |
|---|---|---|
runtime.endpoints.config.enabled | true | Serves the /config endpoint, which returns the merged effective configuration with sensitive values masked. Supports JSON and YAML via content negotiation. |
To trim what an exposed admin port reveals — for example, hide the bootstrap servers from /info and turn off the config dump entirely:
runtime:
endpoints:
info:
show-kafka: false
config:
enabled: false
Health checks (runtime.health)
The readiness and liveness probes aggregate a set of health indicators. Two of them have configurable timeouts here. See Health checks for how the indicators map to /health/live and /health/ready.
| Key | Default | Purpose |
|---|---|---|
runtime.health.kafka-broker.timeout-ms | 2000 | Timeout for the broker connectivity check (via AdminClient). |
runtime.health.schema-registry.timeout-ms | 5000 | Timeout for the Schema Registry connectivity check. This indicator auto-enables only when stoatflow.schema-registry-url is set. |
runtime:
health:
kafka-broker:
timeout-ms: 3000
schema-registry:
timeout-ms: 5000
Logging levels (logging.level)
logging.level is a top-level block (a sibling of stoatflow and runtime, not nested under either). It maps logger names to levels and applies them to Logback at startup, overriding whatever logback.xml set. Use ROOT for the root logger.
logging:
level:
ROOT: INFO
io.stoatflow: DEBUG
org.apache.kafka: WARN
org.apache.kafka.clients.consumer: INFO
Valid levels are TRACE, DEBUG, INFO, WARN, ERROR, and OFF. Per-logger levels can also be set via environment variables with the LOGGING__LEVEL__ prefix — for example LOGGING__LEVEL__ORG_APACHE_KAFKA_CLIENTS=DEBUG sets org.apache.kafka.clients to DEBUG. The single-underscore segments become dots in the logger name. Environment variables take precedence over YAML when both name the same logger.
Kafka client passthrough (stoatflow.kafka)
Kafka client tuning lives under stoatflow.kafka.* (the engine half), not under runtime.* — but it is part of operating a runtime app, so it is worth knowing where it is. The three maps pass properties straight through to the underlying Kafka clients, applied on top of StoatFlow's framework defaults:
stoatflow:
kafka:
consumer:
max.poll.records: 1000
fetch.min.bytes: 65536
producer:
compression.type: lz4
linger.ms: 50
restoration-consumer:
max.poll.records: 5000
A few forced overrides (for example bootstrap.servers, group.id, enable.auto.commit=false, and the transactional settings under exactly-once) cannot be overridden here — they are required for correctness. The full resolution order and the list of forced values are on Kafka client configuration.
linger.ms, max.poll.records). When setting them via environment variables, use the dedicated STOATFLOW__KAFKA__PRODUCER__* / STOATFLOW__KAFKA__CONSUMER__* form (e.g. STOATFLOW__KAFKA__PRODUCER__LINGER_MS=50) — the generic env path would mangle the dotted keys. Details on Kafka client configuration.License (stoatflow.license)
The license block is also under stoatflow.*, not runtime.*, but the :runtime module bridges it to the engine and exposes license state via the /license endpoint and the license health indicator. The minimal form references the key from an environment variable:
stoatflow:
license:
key: ${STOATFLOW_LICENSE_KEY}
environment: prod # required for the Production tier
cache-dir: /var/lib/stoatflow/state/license-cache
The full set of license keys, environment variables, and system properties — plus the production-tier requirements — is documented on License configuration.
Worked example
A production-leaning runtime + logging block: fixed port, debug endpoints off, environment tags on every metric, and a quieter Kafka client logger.
runtime:
http:
host: 0.0.0.0
port: 8080
debug:
enabled: false
metrics:
enabled: true
recording-level: info
common-tags:
env: production
region: eu-west-1
endpoints:
config:
enabled: false
health:
kafka-broker:
timeout-ms: 3000
logging:
level:
io.stoatflow: INFO
org.apache.kafka: WARN
Next steps
- Core configuration — the
stoatflow.*engine half (lanes, barriers, state, watermarks). - Kafka client configuration — the full consumer/producer/restoration passthrough and resolution order.
- Defaults and presets — what you get out of the box and the RocksDB presets.
- REST API and Metrics — what the HTTP server and
/metricsactually serve. - Configuration reference — the complete, generated key list with every default.
Engine configuration (:core)
The :core engine knobs every StoatFlow app sets — application id, brokers, default serdes, lanes, commit-barrier cadence, state dir, changelog, processing guarantee, and event-time coordination — with defaults from source.
Defaults, adaptivity, and presets
Why a minimal StoatFlow config runs well — the opinionated defaults, the parts that self-tune within bounds you set, and the RocksDB presets and tuning knobs you can change.