Skip to content

Configuration Reference

Reference: All application.properties and application.yml configuration keys for Mercury Composable.

At a glance

  • What — every application.properties / application.yml key supported by the framework and its optional modules, with type, default, and description.
  • Why it matters — configuration is how you tune ports, threading, security, and module behavior without touching code.
  • For developers and operators configuring and deploying applications.

Mercury Composable applications are configured through application.properties (or the equivalent application.yml). This page is the exhaustive reference for every configuration key supported by the framework and its optional modules.

Properties are set in src/main/resources/application.properties and can be overridden with JVM system properties (-Dkey=value), which the config reader checks first. Environment variables enter through ${ENV_VAR:default} substitution inside values (and additionally through Spring Boot's own resolution order in rest-spring-4 apps). When both application.properties and application.yml are present, they are merged and .yml values win for overlapping keys (application.yml is merged last).

Tip: In application.yml, dots in property names become nested YAML keys. For example, rest.server.port=8100 becomes:

rest:
  server:
    port: 8100


Application Identity

application.name

Type Default
String application

Human-readable service name shown in the /info actuator response. Falls back to spring.application.name if set.

info.app.version

Type Default
String —

Application version string (e.g. 1.2.3) shown in the /info actuator response.

info.app.description

Type Default
String —

Application description shown in the /info actuator response.

spring.application.name

Type Default
String application

Standard Spring Boot application name; used as a fallback for application.name.


Server

api.origin

Type Default
String *

Value for the Access-Control-Allow-Origin CORS response header.

hsts.feature

Type Default
boolean true

Enable the Strict-Transport-Security response header (HSTS).

oversize.http.response.header

Type Default
boolean false

Allow HTTP response headers up to 16 KB (default limit is 8 KB).

rest.server.port

Type Default
int 8085

Listening port for the built-in reactive HTTP server.

rest.server.ssl-enabled

Type Default
boolean false

Enable TLS on the reactive HTTP server. Requires rest.server.ssl.cert and rest.server.ssl.key.

rest.server.ssl.cert

Type Default
String (path) —

Path to a PEM-format X.509 certificate. Use classpath:// or file:// prefix. Required when rest.server.ssl-enabled=true.

rest.server.ssl.key

Type Default
String (path) —

Path to a PEM-format private key. Use classpath:// or file:// prefix. Required when rest.server.ssl-enabled=true.

server.port

Type Default
int 8085

Fallback listening port used when rest.server.port is not set; also the Tomcat port under Spring Boot.

websocket.binary.size

Type Default
int (framework default)

Maximum WebSocket binary message size in bytes.

websocket.idle.timeout

Type Default
int 60

WebSocket idle connection timeout in minutes.

websocket.server.port

Type Default
int (same as rest.server.port)

Listening port for WebSocket connections. Defaults to rest.server.port.


REST Automation

REST Automation enables declarative HTTP endpoint mapping via a YAML configuration file. Set rest.automation=true and provide a yaml.rest.automation path to activate it. See REST Automation for the full endpoint configuration syntax.

rest.automation

Type Default
boolean false

Enable the REST Automation engine.

spring.mvc.static-path-pattern

Type Default
String /**

URL pattern for serving static resources (Spring MVC).

spring.web.resources.static-locations

Type Default
String (path) —

Spring Boot alias for static.html.folder; checked as a fallback.

static-content.filter.exclusion

Type Default
String (comma-sep) —

URL paths excluded from the static content filter.

static-content.filter.path

Type Default
String (comma-sep) —

URL prefixes that the static content filter applies to.

static-content.filter.service

Type Default
String —

Route name of a function that pre-processes matching static content requests.

static-content.no-cache-pages

Type Default
String (comma-sep) —

URL paths served with Cache-Control: no-cache.

static.html.folder

Type Default
String (path) classpath:/public

Location of static web content (HTML, CSS, JS, images).

yaml.rest.automation

Type Default
String (comma-sep paths) classpath:/rest.yaml

Location(s) of REST endpoint configuration file(s). Multiple files are merged. A missing or empty file degrades gracefully — a warning is logged, no endpoints are rendered, and startup continues.


Event Script / Flow Engine

Flow configuration files are compiled at startup. Each file lists one or more flow definitions identified by flow.id. Multiple comma-separated paths are merged. See Event Script Syntax for the full DSL reference.

max.model.array.size

Type Default
int 1000

Maximum array index size for dynamic list variables in event script data models.

yaml.event.over.http

Type Default
String (comma-sep paths) classpath:/event-over-http.yaml

Location(s) of the event-over-HTTP target mapping configuration.

yaml.flow.automation

Type Default
String (comma-sep paths) classpath:/flows.yaml

Location(s) of Event Script flow definition files. A missing file degrades gracefully (warning logged; no flows deployed), and a flow with structural violations is skipped with an error log — startup continues in both cases. (A task-level data-mapping violation only omits that task: the flow still deploys and fails at runtime when the missing task is reached.)

yaml.journal

Type Default
String (comma-sep paths) classpath:/journal.yaml

Location(s) of the journal configuration (lists routes whose messages are recorded).

yaml.multicast

Type Default
String (comma-sep paths) classpath:/multicast.yaml

Location(s) of the multicast route configuration. Multicast is a local-JVM fan-out: a message sent to a source route is automatically relayed to all listed target routes within the same in-memory event bus. Format: multicast: [{source: "a.route", targets: ["b.route", "c.route"]}]. Not the same as PostOffice.broadcast(), which is a distributed service-mesh operation.


Knowledge Graph (MiniGraph)

graph.model.automation

Type Default
String (comma-sep manifest paths) —

Location of the graph deployment manifest (e.g. classpath:/graphs.yaml) listing the graph model ids the CompileGraph gate compiles at startup; the manifest's own optional location key (default classpath:/graph) says where the model JSON files live. Since 4.12.19 the property accepts a comma-separated list of manifests, each carrying its own location, and when two manifests list the same graph id the later manifest wins — its copy replaces the earlier one, and if that copy is rejected the id is not executable (the yaml.flow.automation convention; a manifest that cannot be loaded is skipped with a warning). When this property is absent, a warning is logged and no graphs are executable — every /api/graph/{graph-id} call answers 404 ("compiled or 404", ADR-0011). Like every property, a JVM system property overrides it for one run (java -Dgraph.model.automation='classpath:/graphs.yaml, file:/tmp/graph/deploy/graphs.yaml' -jar app.jar): the bundled manifest keeps its graphs, and a file:/ manifest beside it deploys an exported graph without a rebuild — the rapid-prototyping path. Only the ids the listed manifests name are executable.

location.graph.temp

Type Default
String (local path) /tmp/graph

Where the Playground's export graph command writes model JSON. Must be a local filesystem path (read/write requirement): either a plain path (/tmp/graph) or the file: form the tutorials use (location.graph.temp=file:/tmp/graph — the prefix is stripped). A classpath: location is rejected with an error and the default is used instead.

graph.traversal.log

Type Default
boolean true

Stepwise traversal logging for deployed graph execution (graph.executor) — the same trail the Playground dry-run prints to its console, emitted as INFO structured records (log.info("{}", map)). Each record carries three keys: text — the traveler-style message (Walk to {node}, Executed {node} with skill {skill} in {time} ms, Graph traversal completed in {time} ms, or Graph traversal aborted: {reason}), graph — the graph id, and id — the run's trace id (fallback: the flow instance id when tracing is off), so an OpenTelemetry dashboard can join these app-log lines with the exported spans and metrics. With log.format=json or compact the record renders as a nested structure that log-analytics platforms (Dynatrace, Splunk, ...) index as key-values; in plain text format the map prints as its string form. Note that the executor deliberately runs as a @ZeroTracing interceptor (the trace is captured once from the initiating event, not re-spanned per node), so its worker thread holds no trace bracket and the app-context-log context block does not accompany these lines in any format — the record's id key is the correlation surface. On by default; set it to false (for example with the runtime override -Dgraph.traversal.log=false) to reduce log volume on busy installations.


Component Scanning & Startup

modules.autostart

Type Default
String (comma-sep or YAML list) —

Route names or flow://<flow-id> identifiers to activate at startup without an inbound request.

spring.component.scan

Type Default
String —

Package for Spring Boot component scanning; used alongside web.component.scan when running with rest-spring-4.

web.component.scan

Type Default
String (comma-sep packages) —

Java packages to scan for @PreLoad, @MainApplication, @BeforeApplication, and @WebSocketService annotations.

yaml.preload.override

Type Default
String (comma-sep paths) —

YAML file(s) that override @PreLoad annotation settings (route name, instance count) without recompiling.


Threading & Performance

By default all functions run on Java 21 virtual threads — this is the platform's sync-over-async contract: blocking-style code (a PostOffice request, a future.get()) suspends only its virtual thread and releases the carrier, so sequential code performs like reactive with none of the ceremony. Use @KernelThreadRunner to pin a function to the kernel thread pool for blocking-I/O operations that are incompatible with virtual threads.

elastic.queue.segment.size.bytes

Type Default
long 16777216 (16 MB)

Size of each spill segment file in the ElasticQueue overflow buffer. The buffer holds the first 20 events per route in memory and spills the overflow to a per-route sequence of append-only segment files under the temp directory; a segment is deleted as soon as it is fully read. Larger segments mean fewer file rolls and fewer deletes; smaller segments reclaim disk sooner under a long backlog. Rarely needs changing.

Tip: put the spill directory on tmpfs. Spill I/O is transient — nothing in the buffer survives a restart — so durability buys nothing here. The one latency blemish measured for the file store is a rare OS dirty-page-flush outlier, which a memory-backed filesystem removes entirely. On Linux, point the JVM temp directory at a tmpfs mount (-Djava.io.tmpdir=/dev/shm/mercury) and size it for your worst-case backlog.

elastic.queue.dispatch.mailbox.size

Type Default
int 1024

Capacity of the per-route dispatch mailbox. The Vert.x event loop enqueues to this bounded queue and a per-route virtual thread drains it, running the state machine and the blocking spill I/O off the loop. When the mailbox fills, the enqueueing loop blocks rather than dropping — back-pressure, not loss — and a warning is logged once per route. Floored at the 20-event memory buffer size.

kernel.thread.pool

Type Default
int 100

Size of the kernel thread pool for @KernelThreadRunner functions. The framework enforces a minimum of 32; there is no hard maximum, but ~200 is advisory — a JVM can rarely sustain more than ~250 kernel threads.

worker.instances.<route>

Type Default
int (from @PreLoad)

Override the concurrency instance count of a function whose @PreLoad declares this key as its envInstances parameter. Declared instance counts are rules of thumb — this key is what lets an operations team tune a function's concurrency in QA and Perf environments before promoting to Production, without a rebuild. The built-ins below all follow the worker.instances.<route> naming convention; your own functions opt in the same way, e.g. @PreLoad(route="my.service", instances=50, envInstances="worker.instances.my.service"). To override the instance count of a function that does not declare envInstances, use yaml.preload.override instead.

worker.instances.actuator.services

Type Default
int 5

One knob for the whole actuator family — actuator.services and its aliases (info.actuator.service, routes.actuator.service, env.actuator.service, health.actuator.service, liveness.actuator.service, lib.actuator.service) share a single worker pool size.

worker.instances.http.flow.adapter

Type Default
int 200

Instance count for the built-in http.flow.adapter (Event Script's HTTP-to-flow adapter).

worker.instances.no.op

Type Default
int 500

Instance count for the built-in no.op placeholder function.

worker.instances.resilience.handler

Type Default
int 500

Instance count for the built-in resilience.handler.

worker.instances.simple.exception.handler

Type Default
int 250

Instance count for the built-in simple.exception.handler.

Keys keep the route's dots as-is: a function declared with envInstances = "worker.instances.v1.get.profile" is tuned by worker.instances.v1.get.profile=100.


HTTP Client

async.http.temp

Type Default
String (path) /tmp/async-http-temp

Temporary folder used to buffer large async HTTP response bodies.

http.client.connection.timeout

Type Default
int (ms) 5000

Connection timeout in milliseconds for the built-in async HTTP client.

event.over.http.format

Type Default
String standard

Serialization format for outbound Event over HTTP calls: standard (the language-neutral wire format, interoperable with the Rust implementation and future ports) or compact (the classic single-character-key format — a fallback for peers on older versions). Inbound decoding always accepts both formats automatically, and the /api/event service replies in the requester's format. Overridable per call (or per target in yaml.event.over.http) with the x-event-format header.


Distributed Tracing & Observability

See the Observability guide for the tracing design and OpenTelemetry/OTLP export; the keys below tune it. The otel.* keys are read by the opentelemetry-forwarder extension.

app.log.context

Type Default
boolean true

Turns the application log context on or off. When on (the default), the structured JSON appenders (log.format=json or compact) stamp a context block — correlation id, trace/span ids, service name — into every log line a traced function emits, using the built-in default-log-context.yaml template. Provide your own app-log-context.yaml on the classpath to replace the template, or set this key to false to opt out. A UTC timestamp is added automatically whether or not your template asks for one — you do not configure it.

log.format

Type Default
String text

Application log output format: text (human-readable), compact, or json.

show.application.properties

Type Default
String (comma-sep list) —

Application property keys to expose via the /env actuator endpoint.

show.env.variables

Type Default
String (comma-sep list) —

Environment variable names to expose via the /env actuator endpoint.

skip.rpc.tracing

Type Default
String (comma-sep list) async.http.request

Route names whose RPC calls produce no caller-side round_trip trace record - an RPC to a listed route folds into the calling function's span. A callback-mode execution of a listed route (the Event-over-HTTP stream relay's client leg) still records its own span; see Observability.

stack.trace.transport.size

Type Default
int 10

Maximum stack-trace lines embedded in an EventEnvelope when an exception occurs.

http.correlation.id.header

Type Default
String X-Correlation-Id

HTTP header carrying the business correlation-id (enterprise-specific; case-insensitive on inbound). Captured at the edge and preserved end-to-end — exposed to flows as model.cid and to functions via PostOffice.getMyCorrelationId(). A fresh dash-less UUID is generated when the header is absent, and the resolved value is echoed on every HTTP response under the same header name so an edge caller can correlate without parsing the body (a response header of the same name set by the function takes precedence). Overridable per endpoint with correlation.id.header in a rest.yaml entry (impedance matching for a legacy caller).

http.trace.id.header

Type Default
String X-Trace-Id

HTTP header recognized (inbound, when no W3C traceparent is present) and emitted (outbound by the async HTTP client) as the trace-id. A well-formed traceparent always takes precedence inbound. Overridable per endpoint with trace.id.header in a rest.yaml entry.

http.traceparent.header

Type Default
String traceparent

HTTP header name carrying the W3C trace context (the full traceparent value: trace-id, parent span-id and flags). When customized, outbound HTTP calls (the async HTTP client and Event-over-HTTP) stamp the same W3C value under both names. Inbound, the standard traceparent always wins — the custom name is read only when the standard header is absent: a well-formed standard traceparent means the caller already speaks W3C/OTel, so a proprietary header alongside it is residual and safely ignored. Overridable per endpoint with traceparent.header in a rest.yaml entry.

Our position: use the standard. traceparent is the W3C Trace Context header that OpenTelemetry and the wider observability ecosystem interoperate on, and the framework implements it as the default with zero configuration. This optional setting exists for backward compatibility with legacy systems only — an intermediary (typically an API gateway with a header allow-list) or an upstream convention that cannot be fixed promptly. Departure from the standard is discouraged: a renamed carrier is invisible to standards-compliant tooling (OpenTelemetry SDKs, service meshes, APM agents) and every participant must be configured alike. Treat a custom name as a temporary bridge, and plan the migration back to the standard header (e.g. fixing the gateway allow-list).

kafka.correlation.id.header

Type Default
String cid

Kafka message header carrying the business correlation-id (no cross-vendor standard exists for non-HTTP transport, so it is configurable). Read inbound by the Kafka Flow Adapter and written outbound by simple.kafka.notification; a fresh UUID is generated inbound when absent. Overridable per binding with correlation.id.header in a kafka-flow-adapter.yaml entry.

kafka.trace.id.header

Type Default
String —

Optional Kafka message header for the trace-id. Inbound: a fallback trace-id source when the upstream sends no W3C traceparent (which always takes precedence). Outbound: simple.kafka.notification stamps the current trace-id under this name alongside traceparent, for legacy downstream consumers. Unset = traceparent-only behavior (unchanged). Overridable per binding with trace.id.header in a kafka-flow-adapter.yaml entry.

kafka.traceparent.header

Type Default
String traceparent

Kafka message header name carrying the W3C trace context — the Kafka twin of http.traceparent.header, for backward compatibility with legacy middleware or an upstream convention only (see the standards position under http.traceparent.header — departure from the standard traceparent name is discouraged). When customized, simple.kafka.notification stamps the same value under both names, and the Kafka Flow Adapter honors the standard traceparent first — the custom name is read only when the standard header is absent. Overridable per binding with traceparent.header in a kafka-flow-adapter.yaml entry.

kafka.health.timeout

Type Default
String (duration) 5s

Timeout for the kafka.health probe - a single Kafka Metadata request (KafkaConsumer.listTopics) issued from the module's consumer template; no consumer group, no offsets, no admin privileges. Add kafka.health to mandatory.health.dependencies (or the optional list) to include the cluster in /health.

kafka.health.startup.grace

Type Default
String (duration) 30s

Start-up grace period for kafka.health: within it the check reports a placeholder healthy status while the Kafka client warms up in the background, so /health never fails or blocks during application start-up. After the first successful probe (or once the grace expires) every check is live and an unreachable cluster fails the check with a 503 status and a key-value message (text + code).

otel.forwarding

Type Default
boolean false

Master switch for OpenTelemetry trace forwarding. The opentelemetry-forwarder extension lives under org.platformlambda, a base scan package, so the jar alone would auto-register its route — the forwarder is therefore annotated @OptionalService("otel.forwarding") and nothing is registered unless this is true. That lets an application carry the dependency while DevOps decides, per environment, whether traces leave the process. Set it in application.properties, or at runtime without rebuilding: java -Dotel.forwarding=true -jar your-app.jar.

otel.exporter.otlp.endpoint

Type Default
String http://localhost:4318/v1/traces

OTLP/HTTP traces endpoint the opentelemetry-forwarder extension exports spans to.

otel.exporter.otlp.timeout

Type Default
int (ms) 10000

OTLP export timeout for the opentelemetry-forwarder extension.

otel.exporter.otlp.connect.timeout

Type Default
int (ms) 10000

TCP/TLS connect timeout for the opentelemetry-forwarder extension's OTLP exporter, separate from the export timeout.

otel.exporter.otlp.compression

Type Default
String none

OTLP request-body compression for the opentelemetry-forwarder extension: gzip or none. gzip cuts egress bandwidth for high trace volumes.

otel.service.name

Type Default
String application.name

service.name resource attribute the opentelemetry-forwarder extension stamps on every exported span.

otel.exporter.otlp.headers

Type Default
String (comma-sep key=value) —

Request headers for the opentelemetry-forwarder extension — where backend API credentials go (e.g. Authorization=Api-Token … for Dynatrace, X-SF-Token=… for Splunk). Source it from the environment with no default — otel.exporter.otlp.headers=${OTEL_EXPORTER_OTLP_HEADERS} — so no secret is hard-coded; unset resolves to no headers.

The otel.* values support ${ENV_VAR:default} substitution, so the forwarder is configured entirely from application.properties while secrets stay in the environment.


Health & Actuators

mandatory.health.dependencies

Type Default
String (comma-sep list) —

Route names of health-check functions that must all report healthy for /health to return HTTP 200.

optional.health.dependencies

Type Default
String (comma-sep list) —

Route names of health-check functions whose failure is reported but does not fail /health.

protect.info.endpoints

Type Default
boolean false

When true, the /info, /routes, /lib, and /env endpoints require an X-App-Instance header.


Spring Boot Integration

These properties are relevant only when using the rest-spring-4 module.

spring.boot.main

Type Default
String org.platformlambda.rest.RestServer

Main class for the Spring Boot application. Override to use a custom entry point.

spring.profiles.active

Type Default
String (comma-sep list) —

Active Spring profiles; enables profile-specific config files (e.g. application-prod.properties).


Service Mesh / Cloud Connector

The service mesh is provided by the optional connectors modules. Set cloud.connector=kafka to enable inter-instance routing through Kafka. See Minimalist Service Mesh for a setup walkthrough.

Core Connector

application.feature.route.substitution

Type Default
boolean false

Enable the route substitution feature to redirect one route name to another at runtime.

cloud.client.properties

Type Default
String (comma-sep paths) file:/tmp/config/kafka.properties, classpath:/kafka.properties

Location(s) of the Kafka client properties file.

cloud.connector

Type Default
String none

Cloud connector type. none disables the service mesh; kafka enables the Kafka connector.

cloud.services

Type Default
String (comma-sep list) —

Additional cloud services to register at startup.

route.substitution

Type Default
String (comma-sep a:b pairs) —

Inline route substitutions where b replaces a. Example: old.route:new.route.

user.cloud.client.properties

Type Default
String (comma-sep paths) file:/tmp/config/second-kafka.properties, classpath:/second-kafka.properties

Location(s) of a second Kafka client properties file for dual-cluster deployments.

yaml.route.substitution

Type Default
String (comma-sep paths) —

YAML file(s) defining route substitution mappings.

Kafka Topic Management

app.partitions.per.topic

Type Default
int 32

Maximum Kafka partitions per application topic.

app.topic.prefix

Type Default
String multiplex

Prefix for auto-generated application Kafka topics.

application.feature.topic.substitution

Type Default
boolean false

Enable topic substitution for pre-allocated Kafka topics.

closed.user.group

Type Default
int 1

Closed user group number for this instance (must be between 1 and max.closed.user.groups).

default.app.group.id

Type Default
String appGroup

Default Kafka consumer group ID for application instances.

default.monitor.group.id

Type Default
String monitorGroup

Kafka consumer group ID for presence monitor instances.

kafka.replication.factor

Type Default
int 3

Replication factor for auto-created Kafka topics.

max.closed.user.groups

Type Default
int 10

Number of closed user groups (range 3–30).

max.virtual.topics

Type Default
int 288

Maximum number of virtual topics (= partitions × topic count).

monitor.topic

Type Default
String service.monitor

Kafka topic name for presence monitoring signals.

presence.properties

Type Default
String (comma-sep paths) file:/tmp/config/presence.properties, classpath:/presence.properties

Kafka connection properties for the presence monitor.

service.monitor

Type Default
boolean false

When true, this instance acts as a presence monitor rather than a regular service node.

yaml.topic.substitution

Type Default
String (comma-sep paths) file:/tmp/config/topic-substitution.yaml, classpath:/topic-substitution.yaml

YAML file(s) defining topic substitution mappings.


Scheduler

These properties are used by the optional mini-scheduler module.

deferred.start

Type Default
boolean false

Defer scheduler startup until triggered manually, e.g. to wait for leader election.

leader.election

Type Default
boolean false

Enable leader election so that only one instance in a cluster runs each scheduled job.

yaml.cron

Type Default
String (comma-sep paths) file:/tmp/config/cron.yaml, classpath:/cron.yaml

Location(s) of the cron job definition file(s). Multiple files are merged.


PostgreSQL (reactive-postgres extension)

These properties configure the optional reactive-postgres extension. postgres.host, postgres.port, postgres.user, and postgres.password are required when the extension is on the classpath.

logging.level.io.r2dbc.postgresql.PARAM

Type Default
String —

R2DBC parameter logging level (e.g. DEBUG). Never set in production — exposes parameter values and may leak PII.

logging.level.io.r2dbc.postgresql.QUERY

Type Default
String —

R2DBC query logging level (e.g. DEBUG). Never set in production — exposes SQL queries.

postgres.connection.pool

Type Default
int 20

R2DBC connection pool size (minimum 5).

postgres.database

Type Default
String postgres

PostgreSQL database name.

postgres.host

Type Default
String —

PostgreSQL server hostname or IP. Required.

postgres.password

Type Default
String —

PostgreSQL password. Required. Supports ${ENV_VAR} substitution.

postgres.port

Type Default
int —

PostgreSQL server port. Required.

postgres.repository.scan

Type Default
String —

Java package(s) to scan for Spring Data R2DBC repositories. Required.

postgres.ssl

Type Default
boolean true

Enable SSL/TLS for the PostgreSQL connection.

postgres.user

Type Default
String —

PostgreSQL username. Required. Supports ${ENV_VAR} substitution.


Minimalist Kafka library

The opt-in minimalist-kafka library routes Kafka topics into Event Script flows and publishes events to Kafka. See the Kafka Flow Adapter guide. The inbound adapter starts only when yaml.kafka.flow.adapter is set; the outbound simple.kafka.notification function registers automatically.

yaml.kafka.flow.adapter

Type Default
String (path) —

Location of the kafka-flow-adapter.yaml binding file (topic -> flow). Unset = inbound adapter disabled.

kafka.producer.enabled

Type Default
boolean true

Whether this cluster's producer is built. Set false on a consume-only leg of a bridge, where the cluster issues no producer credentials and building the client would fail the deployment. simple.kafka.notification stays registered and fails naming this key. A binding that declares dlq-topic while the producer is disabled fails startup — dead letters are published through that same producer, so the contradiction is rejected rather than silently dropping poison messages. The flag is a veto, not a trigger: only the literal false disables, and leaving the default starts nothing not otherwise configured.

kafka.consumer.enabled

Type Default
boolean true

Whether this cluster's consumer is used. Set false on a produce-only leg: no adapter consumer starts even when yaml.kafka.flow.adapter is set, and kafka.health builds its Metadata probe from the producer template instead (filtered to the consumer config surface, so producer-only keys such as acks are dropped) — keeping a one-way bridge health-checkable on both legs. Disabling both clients is allowed and logs a startup WARN.

kafka.producer.properties

Type Default
String (path, or comma-sep fallback list) classpath:/kafka-producer.properties

Producer client config template location. Externalization of configuration is opt-in: point this at a file rendered by the devops pipeline (e.g. file:/tmp/config/kafka-producer.properties), optionally with a classpath fallback.

kafka.consumer.properties

Type Default
String (path, or comma-sep fallback list) classpath:/kafka-consumer.properties

Consumer client config template location. Externalize the same way as the producer template.

kafka.dlq.timeout.ms

Type Default
long (ms) 10000

Confirm-write timeout for the dead-letter publish (broker ack). Flow processing has no timeout knob — the flow's own ttl is the deadline (Kafka is asynchronous).

kafka.flow.max.retries

Type Default
int 3

Retry attempts on a flow-processing failure before dead-lettering.

kafka.flow.retry.backoff.ms

Type Default
long (ms) 500

Pause between retry attempts.

schema.registry.url

Type Default
String (URL) —

Confluent Schema Registry URL. Unset = schema features off (raw byte[]); set to enable the Schema Registry integration (JSON Schema / Avro — Protobuf is not currently supported).

schema.registry.properties

Type Default
String (comma-sep paths) classpath:/schema-registry.properties

Registry client template location; externalize the same way as the producer template. Entries pass verbatim to the Confluent client — authentication (bearer.auth.* OAuth 2.0, basic auth) and SSL. OAuth token endpoint URLs found in a template are auto-registered on the JVM org.apache.kafka.sasl.oauthbearer.allowed.urls allow-list.

schema.registry.cache.ttl

Type Default
duration 30m

Time-to-live for an entry in the in-memory (platform ManagedCache) cache of schemas fetched by id. Positive results only — a not-found id is never cached, so a newly-registered schema is visible immediately. The TTL bounds how long a cached schema is reused before re-fetching; 30m lets schema changes be picked up without a pod restart (lengthen it in production where schemas change rarely). Cleared at startup (rebuildable).

schema.registry.serde.*

Type Default
String (prefix family) —

Pass-through prefix for Confluent serde configuration: every schema.registry.serde.<key> property is handed to the serializer/deserializer as <key> verbatim — e.g. schema.registry.serde.access.key.id=${AWS_ACCESS_KEY_ID} supplies global KMS driver credentials for CSFLE. Omit entirely to use the cloud default credential chain.

schema.registry.consumer.properties / schema.registry.consumer.serde.*

Type Default
String (comma-sep paths) / String (prefix family) — (the flow adapter shares the producer's codec)

Opt-in separate Schema Registry identity for the consumer side. When schema.registry.consumer.properties names a registry client template, the Kafka flow adapter decodes with its own codec built under the schema.registry.consumer prefix — the same schema.registry.url, that template (the producer's file or a second one), schema.registry.consumer.serde.* pass-through overrides on top of it, and its own schema.registry.consumer.cache.ttl — so a CSFLE installation that grants key access through separate produce and consume identity pools can serve both. The consumer codec reads only its own prefix (repeat a schema.registry.serde.* KMS credential under it). Unset or blank: unchanged, one shared codec; schema.registry.url remains the feature switch.

yaml.secondary.kafka.flow.adapter

Type Default
String (location) —

twin-kafka: secondary-cluster adapter config location; unset = secondary inbound adapter off.

secondary.kafka.producer.enabled / secondary.kafka.consumer.enabled

Type Default
boolean true

twin-kafka: the secondary cluster's twins of kafka.producer.enabled / kafka.consumer.enabled, with identical semantics. Each cluster reads only its own keys and names its own key in any resulting error, so a one-way bridge declares its direction as four settings — the shape a managed cluster's per-client credentials actually force.

secondary.kafka.producer.properties / secondary.kafka.consumer.properties

Type Default
String (path, or comma-sep fallback list) classpath:/secondary-kafka-*.properties

twin-kafka: secondary-cluster client template location; same mechanics as the primary templates.

secondary.schema.registry.url / secondary.schema.registry.properties

Type Default
String —

twin-kafka: the secondary cluster's own optional Schema Registry (URL = feature switch; template passed verbatim to the Confluent client). Registries and their schema-id caches are per-cluster.

secondary.schema.registry.consumer.properties / secondary.schema.registry.consumer.serde.*

Type Default
String (comma-sep paths) / String (prefix family) — (the secondary adapter shares the secondary producer's codec)

twin-kafka: the secondary cluster's twin of schema.registry.consumer.properties — an opt-in separate Schema Registry identity for the secondary flow adapter, built under the secondary.schema.registry.consumer prefix against the same secondary.schema.registry.url, with identical semantics (presence is the opt-in, blank stays off, the consumer codec reads only its own prefix).

secondary.kafka.health.timeout / secondary.kafka.health.startup.grace

Type Default
String (duration) fall back to the kafka.health.* globals

twin-kafka: tunables for secondary.kafka.health, the secondary cluster's twin of kafka.health. A bridge lists both: mandatory.health.dependencies=kafka.health, secondary.kafka.health.

secondary.kafka.correlation.id.header / secondary.kafka.trace.id.header / secondary.kafka.traceparent.header

Type Default
String fall back to the kafka.* globals

twin-kafka: outbound header names on the secondary cluster when the two clusters follow different conventions. Each key falls back to its primary kafka.* setting when unset (secondary.kafka.traceparent.header → kafka.traceparent.header → traceparent).

The Kafka connection and security settings (bootstrap.servers, security.protocol, sasl.*, ssl.*, acks, auto.offset.reset) live in the kafka-producer.properties / kafka-consumer.properties template files — not as application.properties keys — so any enterprise installation is configured by editing or overriding those templates. All template values support ${ENV_VAR:default} substitution; bootstrap.servers defaults to ${KAFKA_BOOTSTRAP_SERVERS:127.0.0.1:9092}. The library pins the (de)serializers; the consumer's enable.auto.commit / max.poll.records are a per-binding overlay (see auto-commit below), not a global template setting.

Per-binding fields in kafka-flow-adapter.yaml (all ${ENV_VAR:default}-substitutable): exactly one of topic (literal) or topic-pattern (regex, subscribed via subscribe(Pattern)) is required; exactly one of flow (direct routing: one flow id for every record) or flows (second-level routing: a rule list <selector>(<matcher>) -> <target> picking the target flow://<flow-id> or task://<route> per record, first match wins, mandatory default — see second-level routing); group (optional consumer group, used verbatim; default kafka-flow-adapter.<topic> for a literal topic, required for topic-pattern); partition (optional; pins one partition via manual assignment, mutually exclusive with topic-pattern); schema.enabled (optional boolean, default false; when true, decode the Confluent-framed value to a Map before routing — see the Schema Registry integration); serializer (optional; 'json' = best-effort SimpleMapper decode of the record value on a non-schema topic, raw byte[] kept when parsing fails — mutually exclusive with schema.enabled, see payload prerequisites); ttl (optional duration, default 30s; the deadline for task:// routing targets — flow targets use their own flow ttl); dlq-topic (optional; pre-provisioned dead-letter topic for this binding, used verbatim — no DLQ if omitted); auto-commit (optional boolean, default false; true uses Kafka-native auto-commit instead of manual commit-after-process); and max-poll-records (optional int; overrides the delivery mode's default of 1 for manual-commit or 500 for auto-commit). See the Kafka Flow Adapter guide for the full per-field rationale and validation rules.


Sync-over-Async (sync-over-async extension)

The opt-in sync-over-async extension exposes a synchronous REST request/response over an asynchronous, cross-pod backend using a Redis return route - and generalizes the same rendezvous to a streaming return route for cross-pod progressive rendering. See the Sync-over-Async guide. It is off by default and starts (eagerly connecting to Redis) only when sync.over.async.enabled=true.

Every soa.redis.* key below falls back to the un-prefixed redis.* form when absent. That is backward compatibility for deployments predating the namespace, and for applications running sync-over-async alone. When the distributed cache also runs, configure the two separately and set the whole soa.redis.* connection set — a partial override inherits the other module's credentials through the fallback. See Separate Redis clients, by design.

sync.over.async.enabled

Type Default
boolean false

Master switch. true starts the Redis return-route coordinator at boot.

soa.redis.host

Type Default
String 127.0.0.1

Redis host.

soa.redis.port

Type Default
int 6379

Redis port.

soa.redis.username

Type Default
String — (blank)

ACL/RBAC username; blank = the default user (password-only or no auth). Set it for a named user such as an AWS ElastiCache RBAC user. Source from the environment (${REDIS_USERNAME}). Authentication is identical for standalone and cluster - AWS applies one credential set to the whole replication group.

soa.redis.password

Type Default
String — (blank)

Auth password; blank = no auth. Source from the environment (${REDIS_PASSWORD}).

soa.redis.ssl

Type Default
boolean false

Use TLS (rediss://).

soa.redis.database

Type Default
int 0

Logical Redis database index (standalone only; a Redis Cluster is database 0).

soa.redis.timeout.ms

Type Default
long (ms) 5000

Default Redis command timeout.

soa.redis.cluster.detect

Type Default
String (auto | other) auto

Cluster auto-detection switch. auto probes the seed at start-up (INFO -> cluster_enabled:1 = cluster, otherwise standalone). Any other value (e.g. off) skips the probe and defers to soa.redis.cluster.mode. Falls back to the un-prefixed redis.cluster.detect when absent. See the Sync-over-Async guide.

soa.redis.cluster.mode

Type Default
boolean false

Cluster on/off used when soa.redis.cluster.detect is not auto, and the fallback when an auto probe is inconclusive (e.g. INFO restricted): true = cluster client, false = standalone. The boolean form matches a common cache-config convention, so it can be shared with a co-resident redis.cluster.mode through the fallback. The return route is cluster-safe (every operation single-key; the one two-key delete is split so no command spans two hash slots).

soa.redis.cluster.nodes

Type Default
String — (blank)

Cluster seed nodes as host:port,host:port. Blank = the single soa.redis.host:soa.redis.port seed - enough on its own, since the client discovers the shard topology from any seed (point it at an AWS ElastiCache configuration endpoint). Used only when the resolved selection is cluster.

soa.redis.health.timeout

Type Default
duration 5s

Timeout for the soa.redis.health probe - a single Redis PING on a dedicated connection built from the soa.redis.* parameters (one successful call proves connectivity, TLS, and authentication). Add soa.redis.health to mandatory.health.dependencies (or the optional list) to include the server in /health. (The plain redis.health route name is the health check of the distributed cache module - see Distributed Cache.)

soa.redis.health.startup.grace

Type Default
duration 30s

Start-up grace period for soa.redis.health: within it the check reports a placeholder healthy status while the Redis client warms up in the background, so /health never fails or blocks during application start-up. The probe's configuration is resolved lazily and re-resolved on every rebuild, and an unusable configuration (unbuildable values, or credentials the server rejects - the signature of a vault-published password that has not landed yet) is a passing Waiting for Redis connection status; only a genuine connectivity failure fails the check, with a 503 status and a key-value message (text + code).

sync.return.channel.prefix

Type Default
String svc-return

Prefix for the per-pod Pub/Sub return channel.

sync.route.ttl.seconds

Type Default
long (s) 90

TTL for a one-shot return-route key; should cover the REST timeout plus a buffer.

sync.response.ttl.seconds

Type Default
long (s) 30

TTL for a one-shot rendezvous queue (short rendezvous window).

sync.max.pending.requests

Type Default
int 10000

Per-pod ceiling on in-flight synchronous requests (backpressure).

sync.stream.ttl.seconds

Type Default
long (s) 1800

TTL for a streaming rendezvous's route key and segment queue, refreshed on every post. Session-scale by design - an SSE notification channel legitimately idles for long stretches - and only the crash safety net: completed or closed streams delete their keys eagerly.

sync.max.pending.streams

Type Default
int 1000

Per-pod ceiling on concurrently open streaming rendezvous (backpressure).

All soa.redis.* and sync.* values support ${ENV_VAR:default} substitution.


Distributed Cache

The distributed cache (v1.cache.redis) uses the plain redis.* connection namespace — the same keys as soa.redis.* above without the soa. prefix (redis.host, redis.port, redis.username, redis.password, redis.ssl, redis.database, redis.timeout.ms, redis.cluster.detect, redis.cluster.mode, redis.cluster.nodes) — plus the cache tunables below.

Running the cache alongside sync-over-async? Give each module its own Redis client: redis.* here, the complete soa.redis.* set there. See Separate Redis clients, by design. The soa.redis.* → redis.* fallback exists for backward compatibility (sync-over-async deployed alone), so leaving soa.redis.* unset points both modules at this server — workable, but you then own the eviction risk and share one memory budget. Two clients also mean two probes: mandatory.health.dependencies=redis.health, soa.redis.health.

redis.cache.enabled

Type Default
boolean false

Master switch. true registers the cache action function v1.cache.redis and the redis.health check; false (default) loads neither.

redis.cache.instances

Type Default
int 20

Number of virtual-thread worker instances for v1.cache.redis (function concurrency) - not a connection count. Every instance shares the module's one multiplexed Lettuce connection.

redis.cache.default.ttl

Type Default
duration 1h

Default TTL applied to a write (PUT / MPUT / LIST_PUSH) that omits a ttl header. Every stored key carries a TTL from creation.

redis.cache.key.prefix

Type Default
String — (blank)

Optional namespace prepended to every cache key (and stripped again from MGET results), so multiple applications can share one Redis without colliding.

redis.health.timeout

Type Default
duration 5s

Timeout for the redis.health probe (a single Redis PING on a dedicated redis.* connection). Add redis.health to mandatory.health.dependencies (or the optional list) to include the cache's Redis in /health. Same semantics as soa.redis.health.timeout.

redis.health.startup.grace

Type Default
duration 30s

Start-up grace period for redis.health - a placeholder healthy status while the client warms up, with the same lazy-config / waiting-on-credential semantics as soa.redis.health.startup.grace.

All redis.cache.* and redis.* values support ${ENV_VAR:default} substitution.


Serialization & Content Types

custom.content.types

Type Default
String (comma-sep list) —

Content-type resolver rules in vendor-type -> canonical-type format. Example: application/vnd.acme+json -> application/json.

mime.types

Type Default
Map (YAML only) —

Map of file extension to MIME type. Example: mime.types.svg: image/svg+xml.

snake.case.serialization

Type Default
boolean true

JSON field names use snake_case by default — the cross-language wire convention shared with the Rust engine, whose serialization is snake_case at compile time. Set false for camelCase.


Data Storage

running.in.cloud

Type Default
boolean false

When false, a per-instance subdirectory is created under transient.data.store. When true, the path is used as-is (for ephemeral containers).

transient.data.store

Type Default
String (path) /tmp/reactive

Base directory for the ElasticQueue overflow buffer that absorbs event bursts when consumers are slower than producers.


Complete Example

A typical src/main/resources/application.properties for a REST-serving composable application. This covers the properties most developers will need to configure.

#
# Mercury Composable — Example application.properties
#

# --- Application Identity ---
application.name=my-service
info.app.version=1.0.0
info.app.description=My composable microservice

# --- Server ---
rest.server.port=8100

# --- REST Automation ---
rest.automation=true
yaml.rest.automation=classpath:/rest.yaml
static.html.folder=classpath:/public

# --- Event Script / Flows ---
yaml.flow.automation=classpath:/flows.yaml

# --- Component Scanning ---
web.component.scan=com.example.myapp

# --- Threading ---
# Increase only if many @KernelThreadRunner functions are used.
kernel.thread.pool=100

# --- HTTP Client ---
http.client.connection.timeout=5000

# --- Distributed Tracing ---
# The trace ID travels as the "X-Trace-Id" header and the W3C "traceparent" header (traceId + spanId).
# Both are emitted outbound and accepted inbound; "traceparent" takes precedence on inbound. No config.

# --- Correlation ID ---
# Business correlation-id headers (configurable; defaults shown). Captured at the edge, preserved as
# model.cid, and propagated downstream. A fresh UUID is generated when absent.
http.correlation.id.header=X-Correlation-Id
kafka.correlation.id.header=cid

# --- Health ---
# List health-check routes that must all pass for /health to return 200.
# Add cloud.connector.health when cloud.connector != none.
# mandatory.health.dependencies=cloud.connector.health

# --- Actuators ---
protect.info.endpoints=false

# --- Serialization ---
snake.case.serialization=true

# --- Logging ---
log.format=text

# --- Cloud Connector (uncomment for service mesh) ---
# cloud.connector=kafka
# cloud.client.properties=file:/tmp/config/kafka.properties,classpath:/kafka.properties

See Also