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

Trace persistence settings

Orion’s own per-request trace records — rows in the traces table, read through /api/v1/admin/traces. Unrelated to the OTLP export in [tracing] above; before 1.0 these keys lived under [tracing.storage], which is exactly the confusion the split removes. A channel can override the mode with its config.tracing field; unset per-channel fields fall back to what is set here.

Synopsis

[trace_storage]
mode = "sync"
sample_rate = 1.0
errors_only = false
max_pending = 10000
async_on_overflow = "drop"
overflow_block_timeout_ms = 100
async_workers = 4
batch_size = 1000
batch_flush_interval_ms = 100
batch_workers = 4

Description

ModeBehaviour
syncWrite inline before responding. Strongest durability; throughput capped by single-writer contention.
asyncEnqueue to a bounded background queue, one database write per task.
batchBounded queue; workers commit batch_size rows per transaction. Highest throughput.
offNo persistence at all.

Options

SettingDefaultEnv varWhen to change
trace_storage.mode"sync"ORION_TRACE_STORAGE__MODEA served request implies a persisted trace, at the cost of the DB’s write rate capping throughput. Set batch or async to lift that cap — the request path then runs ahead of the trace table and can overrun max_pending, at which point traces are shed per async_on_overflow.
trace_storage.sample_rate1.0ORION_TRACE_STORAGE__SAMPLE_RATEFraction of traces persisted, 0.0 to 1.0. Applies to sync traces only — an async submission’s trace row is how its result is delivered, so async traces always persist regardless of this rate; bound async storage with errors_only or trace_queue.retention_hours instead.
trace_storage.errors_onlyfalseORION_TRACE_STORAGE__ERRORS_ONLYPersist only traces that ended with errors — a cheap way to keep the table small.
trace_storage.max_pending10000ORION_TRACE_STORAGE__MAX_PENDINGQueue capacity in async and batch modes.
trace_storage.async_on_overflow"drop"ORION_TRACE_STORAGE__ASYNC_ON_OVERFLOWdrop or block. block applies backpressure to the request path.
trace_storage.overflow_block_timeout_ms100ORION_TRACE_STORAGE__OVERFLOW_BLOCK_TIMEOUT_MSHow long block waits for capacity before dropping anyway.
trace_storage.async_workers4ORION_TRACE_STORAGE__ASYNC_WORKERSWorker count in async mode.
trace_storage.batch_size1000ORION_TRACE_STORAGE__BATCH_SIZERows per transaction in batch mode, and the dominant term in how fast the queue drains: measured on SQLite with 4 workers, 100 drains 26k rows/s and 1000 drains 45k rows/s. Max 1000 — the batch INSERT binds ~11 parameters per row against SQLite’s 32 766-bind statement cap.
trace_storage.batch_flush_interval_ms100ORION_TRACE_STORAGE__BATCH_FLUSH_INTERVAL_MSHow long a partial batch waits before flushing.
trace_storage.batch_workers4ORION_TRACE_STORAGE__BATCH_WORKERSWorker count in batch mode; each owns an independent batch.

mode = "off" applies to the synchronous endpoint, where the caller already holds the answer. It does not disable persistence for POST /{channel}/async. Appending /async is a request for a result to be fetched later. The trace row is written before the 202 is returned, so trace_id is always present. off is safe to combine with async channels.

Last verified 14 September 2026