Skip to content

Configuring WebSocket client

The WebSocketClient is the default client used to connect to the Fluxzero Runtime over WebSocket. It provides full access to the event store, message gateways, tracking, search, scheduling, and key-value storage subsystems via configurable, high-throughput sessions.

To configure and instantiate a WebSocket-backed client:

WebSocketClient client = WebSocketClient.newInstance(
WebSocketClient.ClientConfig.builder()
.runtimeBaseUrl("wss://my.flux.host")
.name("my-service")
.build());
Fluxzero flux = DefaultFluxzero.builder().build(client);

This is the most common setup for production and shared environments. It connects to a remote Fluxzero Runtime via the runtime base URL, which must point to the desired deployment.


The client negotiates compression with the Runtime. See Compatibility & dependencies when upgrading an existing deployment.

The ClientConfig class defines all connection, routing, compression, and tracking parameters. It is fully immutable and can be created or extended using the toBuilder() pattern.

Key options include:

SettingDescriptionDefault
runtimeBaseUrlBase URL for all subsystems
(e.g. wss://my.flux.host)
FLUXZERO_BASE_URL or FLUX_BASE_URL
nameName of the applicationFLUXZERO_APPLICATION_NAME or legacy alias
applicationIdOptional app IDFLUXZERO_APPLICATION_ID or legacy alias
idUnique client/process instance IDFLUXZERO_CLIENT_ID, legacy alias; otherwise task-ID-prefixed UUID or UUID
supportedCompressionAlgorithmsPreferred and fallback compression algorithmsZSTD only
pingDelay / pingTimeoutHeartbeat intervals for WebSocket health10s / 15s
maxConcurrentRuntimeWebSocketMessagesMessages decoded or waiting for completion-dispatcher admission per session3
maxRetainedRuntimeWebSocketMessagesTotal assembling, compressed-pending, decode/admission, and active messages128
maxRetainedRuntimeWebSocketBytesTotal compressed runtime wire bytes retained per session64 MiB
maxConcurrentRuntimeResultCompletionsAdmitted groups and result completions/continuations per client8
runtimeIngressStallCloseTimeoutOptional close delay after ingress is diagnosed as stalledDisabled
aggregateHistoryMaxFetchBytesSerialized event-payload bytes requested per aggregate-history pageCount-only in compatibility mode; 100 MiB from defaults version 2026.09.10
disableMetricsWhether to suppress all outgoing metricsfalse
typeFilterOptional message type restrictionnull

FLUXZERO_TASK_ID identifies the hosting platform task or pod; it is not itself a unique process incarnation. When present, the SDK uses it as the recognizable prefix of a generated client ID and publishes the unchanged value as authoritative $taskId correlation metadata. The generated client ID remains stable across WebSocket reconnects, but a newly constructed client receives a new UUID suffix. Set FLUXZERO_CLIENT_ID only when supplying an explicitly unique client-instance ID; FLUX_CLIENT_ID remains available as a legacy alias.

In compatibility mode, failed WebSocket connections retry every second. Set fluxzero.websocket.reconnectBackoff.enabled=true, or use fluxzero.defaults.version >= 2026.09.09, to use equal jitter over capped exponential ceilings of 1, 2, 4, 8, then 16 seconds. A successful connection resets the retry cycle. Set the dedicated property to false to keep fixed retries on a newer defaults profile. The conventional environment-variable name is FLUXZERO_WEBSOCKET_RECONNECT_BACKOFF_ENABLED.


The SDK bounds incoming work so slow callbacks do not consume unlimited resources. It limits retained messages and bytes per connection, and separately limits concurrent decoding and result completion. When capacity fills, the connection pauses receiving until work completes.

Keep the defaults unless measurements show a reason to tune them. Larger retained limits can absorb bursts but use more memory; more completion concurrency permits more callbacks to run at once.

PropertyPurpose
fluxzero.runtime.ingress.maxConcurrencyConcurrent runtime-message decoding per session
fluxzero.runtime.ingress.maxRetainedMessagesRetained runtime messages per session
fluxzero.runtime.ingress.maxRetainedBytesRetained compressed wire bytes per session
fluxzero.runtime.ingress.maxCompletionConcurrencyConcurrent result completions per client
fluxzero.runtime.ingress.stallCloseTimeoutOptional delay before closing a stalled connection, such as PT30S

Use conventional environment-variable names, for example FLUXZERO_RUNTIME_INGRESS_MAX_RETAINED_BYTES. Explicit builder settings take precedence over properties. The byte limit is a work-admission limit, not a maximum response size; one oversized response can still proceed alone.

Set fluxzero.websocket.transportMetrics.enabled=true (FLUXZERO_WEBSOCKET_TRANSPORT_METRICS_ENABLED) for transport diagnostics. A stalled connection has retained work without functional progress; an idle connection is not stalled. The optional stall-close timeout is disabled by default. Consider it when a silent connection failure must be detected even while local backpressure pauses receiving.

Controlled application shutdown disables ingress-stall/recovery diagnostics and stall-triggered connection closure before shutdown callbacks and consumers drain. Connections remain available for pending results, position updates and shutdown publications. This applies to namespace clients as well. If you manage a client lifecycle directly, call Client.prepareShutdown() before draining your own callbacks, then Client.shutDown() to release resources. The same lifecycle applies in Java and Kotlin.

Tracker cancellation waits at most one second across the parallel trackers in a registration. It does not interrupt an active handler or acknowledge unfinished work. A blocked worker runs interceptor cleanup after it eventually exits; custom cleanup must remain bounded. Component shutdown budgets can accumulate, so this is not a global application-shutdown deadline.

For defaults, valid ranges and the exact admission and shutdown contracts, see WebSocketClient.ClientConfig .

Supported wire representations are negotiated automatically with the Runtime. Applications do not configure packed Model substeps. See Compatibility & dependencies for upgrade order and older peers.


Flux opens multiple WebSocket sessions to handle parallel workloads. You can tune the number of sessions per subsystem:

ClientConfig config = ClientConfig.builder()
.eventSourcingSessions(2)
.searchSessions(3)
.gatewaySessions(Map.of(COMMAND, 2, EVENT, 1))
.build();

Each session can multiplex multiple consumers or producers under the hood. Use more sessions to improve parallelism and isolation across critical workloads.


Tracking clients can use local caches to optimize polling performance when many consumers are tracking the same topic or message type.

ClientConfig config = ClientConfig.builder()
.trackingConfigs(Map.of(
EVENT, TrackingClientConfig.builder()
.sessions(2)
.cacheSize(1000)
.build()))
.build();

The cacheSize determines how many messages are buffered in-memory per topic. This helps reduce round-trips to the Runtime and can significantly boost performance in high-fanout projections or handlers.


Once created, the client is passed into the builder:

Fluxzero flux = DefaultFluxzero.builder()
.makeApplicationInstance(true)
.build(webSocketClient);

For testing or lightweight local development, use the in-memory LocalClient instead:

Fluxzero flux = DefaultFluxzero.builder().build(LocalClient.newInstance());

This simulates the entire platform in-memory without external dependencies.



© 2026 Fluxzero