report.csv of 100 MiB. For small JSON, use a regular worker.call(...).
For the underlying model (how channels are addressed, multiplexed, and torn down), see Channels
architecture.
Payload size
The limit applies to the complete serialized UTF-8 JSON envelope, measured in bytes. The Rust, Node, Python, and Go SDKs support messages up to 64 MiB. The browser SDK has a 16 MiB outbound limit and does not fragment messages because browser WebSocket APIs do not expose frame control. Browser workers also have a 16 MiB receive limit. For Rust, Node, Python, and Go, messages up to 16 MiB are sent as one text frame. Larger messages, up to and including 64 MiB, are sent as one fragmented WebSocket text message using multiple frames. The engine sends every message larger than 1 MiB to a worker as one fragmented text message of 1 MiB frames, so no frame it sends exceeds a worker’s frame size limit. Applications send and receive these messages through the usual function APIs. The receiving worker must run SDK version 0.24.5 or later to accept messages larger than 16 MiB. An updated engine checks the serialized envelope against the target worker’s receive limit and returnspayload_too_large to the caller when the target cannot accept it. The engine sets that
limit when the worker registers:
- A browser worker gets 16 MiB.
- A worker that declares the
large-messages.v1protocol feature gets 64 MiB, whatever version it reports. The Rust, Node, Python, and Go SDKs declare it from 0.25.0; the browser SDK does not. - Any other worker gets 64 MiB when the version it reports is an SDK version of 0.24.5 or later,
written as semver (
0.24.6,0.25.0-rc.5) or PEP 440 (0.25.0rc5,0.24.5.post1). It gets 16 MiB when the version is missing, cannot be parsed, or is older, including pre-releases of 0.24.5. Other features, such asobserve.v1, do not count.
large-messages.v1, so the engine relies on the
version they report. A Rust worker on one of them that sets WorkerMetadata.version to its own
version instead of the SDK version therefore stays at 16 MiB. Upgrade it to SDK 0.25.0 or later.
Above 64 MiB, the Rust, Node, Python, and Go SDKs reject the message locally with
payload_too_large; the error message links to this Payload size section. Engines
older than the updated size check forward messages as a single frame without checking the target’s
limit. An older worker may then disconnect if the message is too large for it. Use an engine and
SDKs from the same release, or newer.
The engine reads up to 64 MiB per message from a worker, whether the message arrives as one
frame or as fragments, so it also accepts the single large frames of SDKs older than 0.24.5. When a
worker sends a larger message, the engine drops it and the connection stays open. A call gets
payload_too_large as its result, and when a function returns a result that is too large, its
caller gets payload_too_large instead. Other calls on the connection are not affected. A message
the engine cannot answer, such as a call that expects no result, is dropped and logged.
Observer activations follow the same limits, and the engine keeps at most 64 MiB of one observed
event (every field its observers capture, input and output counted separately). An event over either
limit is not delivered: the observer counts a TOO_LARGE drop and the engine logs a warning. See
Observers / Observed call size.
Use a channel for payloads above 64 MiB. Channels stream payload bytes separately from the JSON
function envelope. See Using channels.
Using channels
A channel is created by one worker and has two local stream ends,writer and reader, and two
serializable refs, writerRef and readerRef, that another function receives in its payload. The
subsections below cover the local ends.
Create a channel
createChannel() returns the channel. Write the payload to writer and close it when finished. The
bytes flow through the engine to whichever worker holds the matching reader.
- Node / TypeScript
- Python
- Rust
- Go
Read from a channel
Read the localreader until the other end closes. The bytes arrive in the order they were written
by whichever worker holds the matching writer. If the writer’s connection ends without a close (it
aborted, crashed or lost its connection), the read fails with an error instead of ending: treat it
as an incomplete transfer. See
Backpressure and lifecycle for how a
writer aborts.
- Node / TypeScript
- Python
- Rust
- Go
Using channels across functions
A channel only becomes useful once two code paths own its ends. Typically one function holds the localwriter / reader and another function receives the matching ref in its payload. The two
subsections below cover that handoff: first how to send a ref alongside a normal call, then how the
receiving function opens the ref to read or write.
Pass a channel ref to another function
Pass thereaderRef (or writerRef) as part of a normal function invocation. The receiving
function uses the ref to read from (or write to) the channel.
- Node / TypeScript
- Python
- Rust
- Go
Read from a channel ref
The receiving function gets the ref in its payload and reads it until the other end closes.- Node / TypeScript
- Python
- Rust
- Go
Write to a channel ref
The receiving function gets the ref in its payload, writes the payload to it, and closes it.- Node / TypeScript
- Python
- Rust
- Go