Skip to main content
Version: 0.6.x

Top-level configuration

An ArkFlow configuration describes the engine: logging, the health-check / control-plane server, the list of streams to run, and optional streaming jobs executed by the unified kernel. The file format is selected by extension — .yaml/.yml, .json, or .toml are all accepted.

logging:
level: info

health_check:
enabled: true
address: "127.0.0.1:8080"

streams:
- id: orders
input:
type: memory # any registered input — see the component pages
pipeline:
processors: [] # optional processors
output:
type: drop # any registered output

jobs: [] # optional declarative streaming jobs, see "job" below

Top-level fields​

FieldTypeRequiredDefaultDescription
streamsarray<stream>yes*—Streams to run.
jobsarray<job>no[]Declarative streaming jobs (DAG + time + state + checkpoint) run by the unified kernel.
loggingobjectnosee belowLogging configuration.
health_checkobjectnosee belowHealth-check and control-plane server.

* Both streams and jobs default to empty lists; a jobs-only configuration is valid (declare streams: [] or omit it).

logging​

FieldTypeRequiredDefaultDescription
levelstringnoinfoLog level: debug, info, warn, error.
file_pathstringno—Write logs to this file instead of stdout.
formatstringnoplainLog format: plain or json.

health_check​

Runs an HTTP server with /health, /readiness, and /liveness endpoints (useful for Kubernetes). The same server also hosts the optional control-plane API and the Hub agent when hub_urls is set (see Control plane).

FieldTypeRequiredDefaultDescription
enabledbooleannotrueStart the health-check / control-plane server.
addressstringno127.0.0.1:8080Listen address.
health_pathstringno/healthOverall health endpoint path.
readiness_pathstringno/readinessReadiness endpoint path.
liveness_pathstringno/livenessLiveness endpoint path.
api_prefixstringno/api/v1Prefix for the versioned control-plane API.
api_tokenstringno—Optional Bearer token protecting the versioned control-plane API: with it set, every /api/v1 endpoint — reads included — answers 401 without a valid Authorization: Bearer header.
insecure_localbooleannofalseExplicitly allow the standalone control API to bind a non-loopback address without api_token. Startup refuses that combination by default; when set, the process starts and logs an error-level warning. Never use this on shared networks.
cors_originsarray<string>no[]Browser origins allowed to call the control API. Empty denies cross-origin calls.
hub_urlsarray<string>no[]Hub addresses for compute-node agent mode, tried in order as failover candidates (see Agent multi-Hub failover). Empty ⇒ standalone mode. Breaking change: replaces the former single-string hub_url field; a config that still declares hub_url fails validation with a migration hint — rewrite hub_url: "http://hub:8080" as hub_urls: ["http://hub:8080"].
node_idstringno—Stable identity this process reports to its Hub.
node_tokenstringno—Shared node registration credential. Never included in reports.
agent_lease_ttl_msintegerno15000Lease duration (ms) a compute node advertises to its Hub.
agent_session_ttl_msintegerno3600000Hard lifetime (ms) of a Hub-issued agent session credential; the Agent re-registers transparently when it elapses.
data_portintegerno—Data-plane listen port for cross-node shuffle. When absent the node runs without a network data plane and never advertises the network_shuffle capability. Set together with data_host on every node participating in a split placement.
data_hoststringno—Routable host peers use to reach this node's data plane (e.g. a LAN IP). Required together with data_port for split placement.
observabilityobjectnosee belowProcess-level Prometheus metrics and health probes (see Observability).

health_check.observability​

Exports process-level observability endpoints. They stay available even when health_check.enabled is false — a pure data-plane deployment (no control-plane API, no Hub) still exposes metrics and probes. The listener binds loopback by default; for production, set an explicit address or rely on host/firewall policy. These endpoints are unauthenticated by design — do not expose this listener to untrusted networks. When the control-plane server is enabled, its router serves the same endpoints and no second listener is started.

FieldTypeRequiredDefaultDescription
enabledbooleannotrueStart the observability listener (unless the control-plane server already serves the endpoints).
addressstringno127.0.0.1:8081Listen address.
metrics_pathstringno/metricsPrometheus exposition endpoint (format 0.0.4).
ready_pathstringno/readyReadiness probe: success once the engine finished starting the configured Streams and Jobs.
live_pathstringno/liveLiveness probe: success while the process is running.

Standalone Hub startup safety​

The standalone arkflow-server control plane is fail-closed by default. Set ARKFLOW_HUB_STORAGE to a durable SQLite path, ARKFLOW_OPERATOR_TOKEN for operator APIs, and ARKFLOW_NODE_TOKEN for Agent registration before binding the Hub beyond loopback. For explicitly local development only, set ARKFLOW_HUB_INSECURE_LOCAL=1 while keeping ARKFLOW_HUB_ADDRESS on a loopback address; this permits volatile state and omitted credentials. The Hub restores durable state before binding its listener, so a recovery error leaves the server unavailable rather than serving a partial view.

The standalone arkflow engine applies the same boundary to its local control API: a non-loopback health_check.address without health_check.api_token refuses to start. Set the token, or explicitly opt in with health_check.insecure_local: true (the engine then starts and logs an error-level warning). With a token configured, every /api/v1 endpoint — reads included — requires the Bearer token; the health probes and the top-level /metrics stay open for probes and scrapers.

note

When the control-plane server is enabled, /ready and /live are also mounted on the server address next to the legacy /health, /readiness, and /liveness endpoints (which keep their original semantics).

Secret references​

Sensitive values (passwords, tokens, key material) do not have to be written into the configuration file. Any string value may embed a reference that is resolved once, when the configuration is materialized — for file configs (--config), for --validate, and for configurations applied through the control plane. The stored/applied configuration keeps the reference text; only the running process holds the resolved value in memory.

SyntaxMeaning
${env:VAR}Value of environment variable VAR; error if unset.
${env:VAR:-default}Value of VAR, or default when unset or empty (${env:VAR:-} allows an explicit empty value).
${file:/path}Content of the file at /path with trailing newlines stripped (e.g. a mounted Kubernetes secret).
${secret:NAME}Value of environment variable ARKFLOW_SECRET_<NAME> (verbatim name) — a dedicated namespace for credentials. Supports :- defaults. In hub-dispatched deployments the Hub pre-resolves these references at rollout dispatch, so agents never need the secret environment.
$${Escape for a literal ${.

Rules and guarantees:

  • References may appear anywhere inside a string value, including nested maps/arrays (host=${env:HOST};port=${env:PORT} works).
  • ${...} forms with unknown schemes are left verbatim (forward compatibility); keys and non-string values are never touched.
  • Resolved values are not rescanned: a secret whose value contains ${...} stays literal (no injection).
  • Resolution errors name the configuration path and the reference — never the secret value.
logging:
level: info

health_check:
api_token: "${env:ARKFLOW_API_TOKEN:-}"

streams: []

If ARKFLOW_API_TOKEN is unset, the process fails at startup with an error like Failed to resolve secret reference at health_check.api_token: environment variable 'ARKFLOW_API_TOKEN' is not set (reference: ${env:ARKFLOW_API_TOKEN}).

note

Resolution is strict everywhere a configuration is materialized. In a Hub–Agent deployment, a configuration referencing node-local secrets must be validated/applied where those secrets resolve (the standalone single-process deployment is unaffected). A central secret store is planned for a later Hub release.

stream​

Each entry in streams is one independent processing pipeline. Stream fields are documented in depth in the Components section; the shape is:

FieldTypeRequiredDefaultDescription
idstringnostream-<index>Stable stream identifier (must be unique; used for WAL identity and Hub reporting).
inputobjectyes—Input component (source).
pipelineobjectyes—Processor pipeline.
outputobjectyes—Output component (sink).
error_outputobjectno—Output that receives batches a processor failed on.
bufferobjectno—Buffer / windowing strategy between input and processors.
durabilityobjectno—Per-stream WAL durability (see Delivery semantics).
stateobjectno—State contract for legacy windows. Declare durability: ephemeral for a non-recoverable window, or use a jobs entry with checkpoints for durable state.
temporaryarray<object>no—Temporary storage tables for joins.

pipeline​

FieldTypeRequiredDefaultDescription
thread_numintegerno1Number of processor worker tasks.
processorsarray<object>yes—Ordered list of processor components.

job​

Each entry in jobs is a declarative streaming job: an operator DAG with explicit event-time, state, checkpoint, and recovery settings. Jobs run locally through the same unified kernel as streams, and the same job shape is what the Hub distributes to compute nodes (see Distributed jobs).

jobs:
- id: local-job
version: 1
parallelism: 1
max_parallelism: 128
operators:
- { id: source, kind: source }
- { id: sink, kind: sink }
edges:
- { id: e1, from: source, to: sink, partitioned: true }
sources:
- operator_id: source
input_type: generate
config: { type: generate, context: '{"value": 1}', interval: 1s, batch_size: 10 }
time:
mode: processing_time
sinks:
- operator_id: sink
output_type: stdout
recovery: latest_checkpoint
FieldTypeRequiredDefaultDescription
idstringyes—Stable job identifier; must be unique across jobs.
versionintegeryes—Job version; state-format compatibility on recovery is evaluated against it.
parallelismintegerno1Default task parallelism.
max_parallelismintegerno128Upper bound used for key-group partitioning.
operatorsarray<object>yes—DAG nodes: id, kind (source, map, filter, aggregate, window, sink, udf); join is reserved but rejected until a distributed multi-input runtime exists.
edgesarray<object>no[]DAG edges: id, from, to, partitioned (key-group routing instead of same-subtask).
sourcesarray<object>no[]Attach a component input to a source operator: operator_id, input_type, config, time.
sinksarray<object>no[]Attach a component output to a sink operator: operator_id, output_type, config.
stateobjectno—backend (e.g. embedded_kv), durability (durable by default or explicit ephemeral), optional stable root (or ARKFLOW_STATE_ROOT), namespace, ttl_ms, format_version, max_pending_transactions (positive; default 4096; raise it when a window sees very high per-window key cardinality, since one transaction is held per open window group or unacknowledged output), optional positive max_bytes live-state budget. Required by stateful operators; durable state also requires checkpoint.
checkpointobjectno—interval_ms, retention, object_store_uri (e.g. file://... or s3://...).
recoverystringnolatest_checkpointlatest_checkpoint, latest_savepoint, or fail.

time (source event-time declaration)​

FieldTypeRequiredDefaultDescription
modestringyes—event_time or processing_time.
timestamp_fieldstringno—Field read as the event timestamp when mode: event_time.
watermarkobjectno—strategy (bounded_out_of_orderness (default) or monotonous), out_of_orderness_ms, idle_timeout_ms.
allowed_lateness_msintegerno0How far past the watermark late events are still accepted.
late_event_policystringnodropWhat happens to late events: drop, route, or update.
late_event_routestringno—Operator receiving routed late events when the policy is route.
note

Intermediate operator kinds (map, filter, aggregate, window, join, udf) are primarily produced by the streaming SQL compiler and the console DAG orchestrator today. Always run --validate before deploying: it performs the same deep build checks as startup and rejects unsupported operators or state backends explicitly. ./target/release/arkflow schema emits the authoritative JSON Schema, including the jobs fields, for editor completion.

Validate before running​

Always validate a config first:

./target/release/arkflow --config config.yaml --validate

Or emit the full JSON Schema and point your editor at it for field-level completion:

./target/release/arkflow schema > arkflow.schema.json

A pre-generated schema ships with the documentation at /config-schema.json; see IDE auto-completion for editor setup.