Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Retry safety

Orion retries a task in more places than a workflow author has in mind. The trace DLQ replays a failed async delivery, a Kafka redelivery re-runs everything after an uncommitted offset, and http_call retries its own transport failures. Whether that is harmless depends on the function.

Description

This is a different question from whether an error was transient. Orion already classifies that per error — a connection failure is retryable, a rejected query is not. The table below answers the other half: if the retry happens, what does it cost? GET /api/v1/admin/functions serves the same answer per function as retry_safety, so tooling can read it rather than hard-coding this table.

Answers

AnswerMeaning
pureNo effect outside the message. Free to retry.
readObserves state without changing it. A retry costs a round trip and may see a newer value.
idempotent_writeWrites, but a second run lands the same end state.
unsafe_writeWrites, and a second run duplicates the effect — the second email, the second record.
depends_onThe task decides, and the answer carries the input to look at.

Functions

FunctionRetry safetyNotes
cryptopureLocal computation.
jwt_signpureLocal signing.
model_inferpureThe graph is a function of its inputs and its weights; a retry re-runs it and lands the same tensors.
storage_presignpureSigV4 arithmetic over the connector’s credentials; zero bytes move.
cache_readread
db_readread
data_queryread
mongo_readread
mongo_aggregatereadAggregation pipelines with $out/$merge are refused by the stage allowlist, so this stays a read.
storage_headreadMetadata only.
jwt_verifyreadMay fetch a JWKS document; the cache usually answers.
cache_writeidempotent_writeThe same key and value land the same entry. A ttl restarts from the retry.
send_emailunsafe_writeA retry sends a second message.
publish_kafkaunsafe_writeA retry publishes a second record. Consumers that need exactly once delivery should dedupe on a key the workflow sets.
http_calldepends_on methodGET/HEAD are safe; POST/PATCH may already have been applied. This is what the connector’s retry_non_idempotent flag is about — off by default.
db_writedepends_on sqlRaw SQL: an UPDATE … SET x = 1 is idempotent, an INSERT is not.
data_writedepends_on opupsert and delete are idempotent; insert is not; update depends on the expression.
mongo_writedepends_on opSame split: an upsert repeats safely, an insert does not.
channel_calldepends_on channelThe answer is whatever the target channel’s workflow does.

Every engine built-in (map, filter, parse_json, …) is pure: they read and write the message and nothing else. log writes to this node’s own observability output, which a retry repeating is not a duplicated effect in the sense above.

Last verified 14 September 2026