Why it matters
A worker runs your piece code inside a sandbox with a bounded memory budget (about 1 GB, minus overhead — see Limits). Reading a large file into aBuffer holds the entire file in that budget at once, so a big enough file exhausts the
memory and the worker is OOM-killed.
Streaming avoids this: the bytes flow through as a Node Readable, roughly 5 MB at a
time, so no process ever holds the whole file. The transfer is transparent — there are no
extra “chunk” steps in your flow; a streaming action looks and behaves like any other.
When to use it
Which approach should you use?
- Buffer (a
Buffer, the default) — small files of known size where holding the whole file in memory is cheap and simple. - Stream (a
Readable) — large files, files of unknown size, or app-to-app transfers (e.g. downloading a large object from one service and uploading it to another) where buffering would risk exhausting memory.
Pieces that support streaming
Streaming is enabled per action. “In” means the action reads its input file as a stream; “out” means it writes the file it produces out as a stream.
More pieces are being enabled over time. Actions not listed here still work — they buffer
the file in memory, which is fine within the size limit.
Stream CSV to Subflows streams a CSV straight from the URL you give it and never writes the
file into storage, so it is the one entry above that does not need S3 file storage.
Per-service upload ceilings
Streaming removes the memory ceiling, not the destination API’s own limit. Where a service caps what a single request can carry, the action switches to a chunked upload session above that cap:
These are pre-existing API limits rather than streaming limits, and each action now handles its own.
One difference matters if your source doesn’t report a size: Dropbox’s session is offset-based, so it
just streams the chunks as they arrive, while Graph wants the file’s total length in every fragment’s
Content-Range header — so the two Microsoft actions buffer once to learn the length before they can
chunk. Give those a source that reports Content-Length when you can.
Building streaming actions
If you are building a piece, you can stream on both sides: read an input file as a stream, and write an output file as a stream.Writing a file as a stream
ctx.files.write accepts a Buffer or a Readable. Pass a Readable — such as an S3
object body or a streaming HTTP response — and it streams straight to storage instead of
being buffered. It returns a file reference string you return from the action, exactly like
the buffered form (see Files).
Reading a file as a stream
Addstreaming: true to a Property.File. The property then resolves to an
ApStreamingFile instead of an ApFile:
body directly. How you hand it to the destination depends on what that destination’s
client accepts — in order of preference:
1. A chunking uploader (best). Accepts a stream of unknown length and buffers each part
before sending it, so no content length is needed and parts are individually replayable. For S3
that is Upload from @aws-sdk/lib-storage; for Azure Blob Storage,
blockBlobClient.uploadStream.
Readable as-is — Google
Drive’s media.body, SFTP’s client.put. Just pass file.body.
3. A single-request HTTP upload. If the destination is a plain PUT/POST that needs an
explicit Content-Length, you have to use file.size — and size is best-effort, so this
path needs a buffered fallback for when it is missing. Dropbox, SharePoint and OneDrive all
look like this:
size is informational and best-effort — it is undefined when the source reports no
Content-Length, and it is also dropped when the response is compressed
(Content-Encoding: gzip/br/deflate), because the decompressed body no longer matches the
advertised length. Don’t require it: prefer pattern 1 or 2, which never need it.
Limits & storage
- Writing into storage is capped. A stream passed to
ctx.files.writeis counted againstAP_MAX_FILE_SIZE_MB(Cloud: 10 MB, self-hosted default: 25 MB) while the bytes flow; exceeding it aborts the transfer and fails the step. See Limits. - Reading a streamed input is not capped. A
streaming: truefile input has noAP_MAX_FILE_SIZE_MBceiling — that is deliberate, since the point of the feature is to move files larger than the cap out to an external service. - Storage backend. Streaming end-to-end requires S3 file storage — see the callout at the top of this page.