Message transports

Configure message transport plugins for communication between workers and server.

The Resonate Server delivers task messages to workers over a configurable set of transports. As of v0.9.5, four transports ship in the server binary:

TransportAddress schemeEnable flagDefault
HTTP pushhttp:// / https://--transports-http-push-enabledtrue
HTTP poll (SSE)(used by SDK clients that long-poll the server)--transports-http-poll-enabledtrue
GCP Pub/Subgcps://--transports-gcps-enabledfalse
Bash execbash:///--transports-bash-exec-enabledfalse

Each transport can be turned on or off independently. The full CLI flag list is on the Run a server page; the equivalent resonate.toml keys live under [transports.<name>].

HTTP push#

The HTTP push transport delivers task messages by POSTing to a worker URL embedded in the task address (for example https://workers.example.com/tasks). It's enabled by default and needs no further configuration for unauthenticated targets.

For deployments where the target service requires authentication, the server can sign outbound requests with a static bearer token or a GCP OIDC ID token. See Outbound HTTP push authentication on the Security page.

HTTP poll (SSE)#

The HTTP poll transport lets SDK clients receive tasks over a long-lived Server-Sent Events stream instead of an inbound HTTP push. It's enabled by default and requires no per-deployment configuration; concurrency limits are tunable via --transports-http-poll-max-connections and --transports-http-poll-buffer-size.

GCP Pub/Sub#

The GCP Pub/Sub transport puts task messages onto Pub/Sub topics for consumption by SDK clients using the matching client-side plugin.

Enable it at runtime with the GCP project ID:

code
resonate serve \
  --transports-gcps-enabled true \
  --transports-gcps-project my-gcp-project-id

Or in resonate.toml:

code
[transports.gcps]
enabled = true
project = "my-gcp-project-id"

Or via env var: RESONATE_TRANSPORTS__GCPS__ENABLED=true and RESONATE_TRANSPORTS__GCPS__PROJECT=my-gcp-project-id.

Authentication uses Application Default Credentials (ADC) — make sure the server process has access to credentials with publish rights on the target project.

Bash exec#

The bash exec transport runs a shell command on the server host for each delivered task. It's intended for local-process workers, lightweight wrappers around CLI tools, and self-hosted single-host deployments where running a separate worker process is overkill.

The transport is disabled by default. Enable it explicitly:

code
resonate serve --transports-bash-exec-enabled true

Or in resonate.toml:

code
[transports.bash_exec]
enabled = true
# Required for named scripts; not required for inline scripts.
root_dir = "/etc/resonate/scripts"
# Working directory for named-script execution. One of:
#   "<root>"   — CWD is set to root_dir (default)
#   "<script>" — CWD is set to the script's parent directory
#   any path   — CWD is set to that literal path
working_dir = "<root>"
Security

The bash exec transport runs arbitrary shell commands as the user running the server. Only enable it on hosts where every promise creator is trusted, and prefer named scripts (with root_dir set to a non-writable directory) over inline scripts in production.

Address forms#

A task address controls how bash exec runs the command:

AddressModeWhat runs
bash:///InlineThe script body is param.data on the promise (base64-encoded)
bash:///relative/path.shNamed scriptThe file at <root_dir>/relative/path.sh is invoked with arguments from param.data

In both modes the server sets RESONATE_PROMISE_ID in the script's environment so the script can correlate logs, metrics, or follow-on calls back to the originating promise.

Inline scripts#

For inline scripts, set the promise's param.data to the base64-encoded script body:

code
echo -n 'echo "hello from $RESONATE_PROMISE_ID"' | base64
# ZWNobyAiaGVsbG8gZnJvbSAkUkVTT05BVEVfUFJPTUlTRV9JRCI=

Then create a task targeting bash:/// with that base64 as param.data. The server invokes bash -c "<decoded script>".

Named scripts#

Set bash_exec.root_dir in config, place an executable script at e.g. <root_dir>/build/release.sh, and target bash:///build/release.sh. Pass arguments by setting param.data to a JSON array of strings:

code
["v1.2.3", "production"]

The server invokes bash <root_dir>/build/release.sh v1.2.3 production with RESONATE_PROMISE_ID in the environment.

Settle behavior#

The promise is settled from the script's exit status:

  • Exit 0 — the promise resolves with the script's stdout (trimmed of trailing whitespace) as the resolved value.
  • Exit non-zero — the promise rejects. The rejection reason is the script's stderr if non-empty, otherwise the literal string exit code N.

A failure to spawn bash, a missing named script, or malformed param.data (e.g. non-array JSON for a named script) all cause the promise to reject with a descriptive reason.

While the script runs, the server refreshes the task lease at one third of tasks.lease_timeout so long-running scripts don't lose their lease.

Planned#

The transports below are specified in the Message Passing Protocol but are not yet implemented in the current server.

Kafka#

Heads up: @resonatehq/kafka NPM plugin is legacy

The published @resonatehq/kafka NPM plugin (v0.1.x) targets the legacy Go-based Resonate Server. It does not work with the current Rust server (v0.9.x). Use the Kafka worker pattern today; native kafka:// transport is on the roadmap below.

Not available in the current server. Native kafka:// transport is on the roadmap.

For Kafka integration today, use a normal Kafka consumer to dispatch a Resonate workflow per message — see the Kafka integration guide and the Kafka worker example.

The published @resonatehq/kafka plugin (and the resonatehq/resonate-transport-kafka-ts repo) targets the legacy Go server and does not work against the current Rust server. Don't install it expecting it to wire up.

SQS#

Not available in the current server. AWS SQS transport support is on the roadmap.