Appearance
Payload Limits
Cyclone checks every external JSON payload before the database write. One value that is too large cannot use an unlimited amount of database memory. That value cannot use an unlimited amount of network memory. That value cannot use an unlimited amount of worker memory.
Three limits apply. The limits are independent. Each limit uses the encoded JSON bytes. Those bytes are the output of json.Marshal. The limit does not use the size of the value in memory.
| Payload | Default | Applies to |
|---|---|---|
| Input | 1 MiB (DefaultMaxInputBytes) | Workflow inputs, Enqueue* inputs, DAG Lit node inputs, schedule inputs |
| Output | 1 MiB (DefaultMaxOutputBytes) | Handler return values |
| Signal | 256 KiB (DefaultMaxSignalBytes) | One Signal payload |
What Happens at the Limit
A payload at the limit is accepted. One byte over the limit is rejected.
- Cyclone rejects an input before any database write.
Enqueue,Submit,Schedule*, and theirTxandManyvariants return a*PayloadTooLargeError.errors.Is(err, cyclone.ErrPayloadTooLarge)also matches that error. A rejected batch inserts nothing. The error names the input index that failed. - Cyclone rejects a signal the same way. Cyclone stores nothing in the mailbox.
- Cyclone cannot check an output before the handler executes. When the encoded output is over the limit, the handler fails permanently. A retry would produce the same output. Cyclone discards the step. The error column contains the text of
PayloadTooLargeError. Withctx.CompletionTx(), the business writes roll back too. An output that cannot be stored must not commit its side effects.
Changing the Limits
go
client, err := cyclone.NewClient(pool, mux,
cyclone.WithPayloadLimits(cyclone.PayloadLimits{
InputBytes: 4 << 20, // raise inputs to 4 MiB
SignalBytes: -1, // disable the signal bound entirely
// OutputBytes: 0 keeps the default
}),
)A zero field keeps the default. A negative field disables that limit. Each client has its own limits. The library enforces the limits. The database does not enforce the limits. Set the same limits on every process that writes a payload.
For a write that bypasses the Go API, add your own CHECK (octet_length(payload::text) <= ...) constraint. Cyclone does not ship that constraint. A fixed database constraint would conflict with a per-client WithPayloadLimits override.
An input from an upstream output (From, FromAll) is already under the output limit. The output limit applies when that upstream step completes. The gathered output of a WaitN node can reach n × SignalBytes.
The output limit also bounds the collected output of a fan-out node. That output is the item outputs in one JSON array. Submit copies the limit of its client onto the node. A larger collected output discards the node permanently. The error has the text of a *PayloadTooLargeError. Each item input is one element of the upstream output. The output limit of the upstream step already bounds that element.
Validate a payload from an untrusted caller at the boundary. Cap that payload at the boundary. The Cyclone limits are a backstop. The Cyclone limits are not input validation.