seppv0.1.0
Reference

Configuration

Every sepp.toml key with type, default, hot-reloadable flag and description.

Configuration is loaded from three layers, in order of increasing priority:

  1. Built-in defaults (the values listed in the tables below)
  2. The sepp.toml file
  3. SEPP_-prefixed environment variables

See the configuration guide for how the file is resolved, how hot-reloading works and the available editing paths. This page is the exhaustive key catalogue.

[server]

gRPC server bind address, data directory, TLS and queue creation policy.

KeyTypeDefaultHot-reloadDescription
listen_addrstring (socket address)0.0.0.0:50051restart-onlygRPC server bind address.
db_pathstring"./sepp-data"restart-onlyDirectory for the durable database. Must be non-empty.
tls_cert_pathoptional stringnonerestart-onlyTLS certificate path for the gRPC listener. Set only together with tls_key_path.
tls_key_pathoptional stringnonerestart-onlyTLS private key path for the gRPC listener. Set only together with tls_cert_path.
strict_queuesbooleanfalseyesWhen false, the first enqueue to an unknown queue implicitly creates it. When true, undeclared queues are rejected with UnknownQueue.

TLS requires both cert and key

Setting only one of tls_cert_path / tls_key_path is rejected at startup. Set both or leave both unset. The same rule applies to [admin] TLS.

[admin]

The admin web UI listener, its keys, and session management. Admin TLS is independent of [server] TLS, though both may point at the same certificate files.

KeyTypeDefaultHot-reloadDescription
enabledbooleantruerestart-onlyServe the admin web UI.
listen_addrstring (socket address)127.0.0.1:9465restart-onlyAdmin UI bind address.
tls_cert_pathoptional stringnonerestart-onlyTLS certificate path for the admin listener. Both or neither.
tls_key_pathoptional stringnonerestart-onlyTLS private key path for the admin listener. Both or neither.
keysoptional array of tablesnoneyesNamed API keys for admin authentication. Omit to disable auth (loopback bind required).
session_ttl_msinteger43200000 (12 h)yesLogin session validity in milliseconds. Range: 60000 (1 minute) to 31536000000 (365 days).
stats_history_msinteger3600000 (1 h)yesDashboard rate history retention in milliseconds, one sample per second per queue, held in memory. Range: 60000 (1 minute) to 21600000 (6 hours).

Each entry in keys is a table with three fields:

FieldTypeDefaultDescription
namestring(required)Key identifier. Must be non-empty and unique across all keys.
keystring(required)Secret value. Must be non-empty and unique across all keys.
rolestring enum"admin"One of "viewer", "operator", or "admin".

Role capabilities

Viewer can read dashboards and the redacted config. Operator can enqueue, manage dead letters and requeue jobs on top of viewer access. Admin has full access including queue CRUD and config edits. See the admin UI guide for details.

Non-loopback requires keys

Binding the admin UI to a non-loopback address without setting keys is rejected at startup. Use TLS (tls_cert_path / tls_key_path) for transport encryption, or terminate TLS in a reverse proxy in front of sepp.

[auth]

gRPC API key authentication for clients (producers and workers).

KeyTypeDefaultHot-reloadDescription
api_keysoptional array of { name, key } tablesnoneyesNamed gRPC API keys. Omitted allows all connections, [] denies all, otherwise only the listed keys are accepted. The name labels the client in the admin UI; only the key is secret. Names must be unique and so must keys.

gRPC vs admin auth

[auth] keys protect the gRPC endpoint used by SDKs. [admin] keys protect the web UI. They are entirely separate; you can have one, both, or neither. See Authentication & TLS for the full picture.

[limits]

Global ceilings checked against every request. Most limits can be overridden per-queue via a [[queues]] entry.

KeyTypeDefaultHot-reloadDescription
max_lease_duration_msinteger300000 (5 min)yesMaximum lease time a worker may claim. Range >= 1.
default_max_attemptsinteger3yesDefault retry count before dead-letter. Range >= 1. May not exceed max_attempts_ceiling.
max_attempts_ceilinginteger100yesHard ceiling on a job's max_attempts field. Range >= 1. Must be >= default_max_attempts.
default_priorityinteger0yesDefault priority when the client omits it. Range 0 to 9; higher is more urgent.
retry_delay_msinteger0yesDelay before redelivering a nack that carries no explicit retry directive. 0 retries immediately. Must not exceed retry_delay_max_ms.
retry_backoff"none" or "exponential""none"yes"none" waits retry_delay_ms on every retry; "exponential" doubles the delay each attempt. Up to 25% jitter is subtracted either way.
retry_delay_max_msinteger3600000 (1 h)yesHard cap on a policy retry delay. Range >= 1.
max_reserve_batchinteger256yesLargest batch a Reserve call may claim. Range >= 1.
max_reserve_queuesinteger32yesMaximum queues per Reserve call. Range >= 1.
max_wait_timeout_msinteger300000 (5 min)yesClamps the Reserve wait timeout. Range >= 1.
max_enqueue_batchinteger256yesLargest batch in EnqueueBatch and EnqueueAtomic. Range >= 1.
max_queue_depthoptional integernone (unlimited)yesCap on live jobs per queue. Omit for unlimited; 0 rejects every enqueue; a positive number enforces a hard cap.
max_payload_bytesinteger1048576 (1 MiB)yesLargest individual job payload. Must not exceed max_message_bytes.
max_message_bytesinteger16777216 (16 MiB)restart-onlygRPC decode ceiling for the entire request. Must be >= max_payload_bytes. Range >= 1.
max_custom_entriesinteger64yesMaximum key-value pairs in the job's custom map. Range >= 1.
max_custom_total_bytesinteger16384 (16 KiB)yesMaximum total key-plus-value bytes in the custom map. Range >= 1.
max_custom_key_bytesinteger256yesMaximum bytes per custom map key. Range >= 1.
max_queue_name_bytesinteger512yesMaximum queue name length. Range 1 to 65535 (on-disk key format limit).
max_job_type_bytesinteger256yesMaximum job_type string length. Range >= 1.
max_idempotency_key_bytesinteger256yesMaximum idempotency key length. Range >= 1.
max_schedule_horizon_msinteger2592000000 (30 days)yesFurthest point in the future a job may be scheduled. Range >= 1.
allowed_encodingsoptional array of stringsnone (accept all)yesAccepted payload encoding values. Omit to accept any. [] rejects all. ["json", "protobuf"] allows only those. Each entry must be non-empty.

Limits that gate restart-only fields

max_message_bytes is restart-only because it controls a low-level gRPC decoder parameter. max_payload_bytes is hot-reloadable but must never exceed max_message_bytes; invalid combinations are rejected at load time and on every hot-reload, leaving the previous config in place on failure.

[storage]

Durability, the background maintenance sweeper, deduplication, dead-letter retention, and the underlying fjall engine knobs. Every field in this section is restart-only.

KeyTypeDefaultHot-reloadDescription
persist_modestring enum"sync_all"restart-onlyDurability mode. See the modes table below.
sweep_interval_msinteger1000restart-onlyMaximum time between maintenance sweeps (safety backstop). Range >= 1.
sweep_limitinteger10000restart-onlyMaximum jobs touched per sweep. Range >= 1.
dedup_window_msinteger86400000 (24 h)restart-onlyHow long an idempotency key is remembered for deduplication. Range >= 1.
dead_letter_retention_msinteger0 (disabled)restart-onlyHow long dead-lettered jobs are retained. 0 (the default) disables the dead-letter store entirely: failed jobs are deleted on the spot.
command_queue_capacityinteger4096restart-onlyCapacity of the committer channel. Range >= 1.
cache_size_bytesoptional integernone (fjall default)restart-onlyBlock cache size in bytes. Range >= 1.
max_journaling_size_bytesoptional integernone (fjall default: 512 MiB)restart-onlyWrite-ahead log size ceiling. Minimum 67108864 (64 MiB).
max_cached_filesoptional integernone (fjall default)restart-onlyOpen file-descriptor cache limit. Minimum 10.
worker_threadsoptional integernone (fjall default: min(cpus, 4))restart-onlyFlush and compaction thread count. Range >= 1.

Persist modes

ModeBehaviour
"sync_all"fsync data and metadata on every commit. Strongest durability.
"sync_data"Flush data with fdatasync, skip extra metadata sync. Faster commits than sync_all.
"buffer"No fsync; relies on the OS page cache. Maximum throughput, not crash-safe.

Buffer mode is not crash-safe

In "buffer" mode an acknowledged enqueue lives only in the OS page cache. An OS crash or power loss can lose writes the kernel has not yet flushed. The server logs a warning at startup when this mode is active.

[logging]

Log output level and format. The entire section is restart-only.

KeyTypeDefaultHot-reloadDescription
levelstring"info,lsm_tree=warn,fjall=warn"restart-onlyLog filter string (RUST_LOG syntax). The RUST_LOG environment variable overrides this value.
formatstring enum"text"restart-onlyOutput format: "text" or "json".

[tracing]

OpenTelemetry trace export. The entire section is restart-only.

KeyTypeDefaultHot-reloadDescription
enabledbooleanfalserestart-onlyEnable OTLP trace export.
otlp_endpointstring"http://localhost:4317"restart-onlyOTLP collector URL.
service_namestring"sepp"restart-onlyservice.name resource attribute. Must be non-empty when enabled is true.
sample_ratiofloat1.0restart-onlyHead sampling ratio. Range 0.0 to 1.0.

[metrics]

OpenTelemetry metric export and the standalone Prometheus scrape endpoint. The entire section is restart-only.

KeyTypeDefaultHot-reloadDescription
enabledbooleanfalserestart-onlyEnable OTLP metric export.
otlp_endpointstring"http://localhost:4317"restart-onlyOTLP collector URL. Must be non-empty when enabled is true.
export_interval_msinteger5000restart-onlyMetric flush interval in milliseconds. Must be > 0 when enabled is true.
prometheus_enabledbooleanfalserestart-onlyExpose a standalone Prometheus /metrics scrape endpoint.
prometheus_listen_addrstring (socket address)0.0.0.0:9464restart-onlyPrometheus scrape bind address.

The Prometheus endpoint is independent of OTLP and can be enabled without it. It is a plain-text HTTP endpoint; place a reverse proxy or firewall in front of it when exposing it beyond localhost.

[[queues]] overrides

An array of tables declaring named queues with per-queue limit overrides. Every field except name is optional and falls back to the global value from [limits] or [storage] when omitted. Adding or removing a [[queues]] entry is itself hot-reloadable; the queue registry swaps atomically.

KeyTypeDefaultHot-reloadDescription
namestring(required)Queue name. Must be valid (not empty, not "." or "..", no /, no control characters) and unique across all entries.
max_lease_duration_msoptional integerfalls to globalyesPer-queue lease ceiling.
default_max_attemptsoptional integerfalls to globalyesPer-queue retry budget.
max_attempts_ceilingoptional integerfalls to globalyesPer-queue attempt ceiling.
default_priorityoptional integerfalls to globalyesPer-queue default priority (09).
retry_delay_msoptional integerfalls to globalyesPer-queue retry delay for directive-less nacks.
retry_backoffoptional stringfalls to globalyesPer-queue backoff curve ("none" or "exponential").
retry_delay_max_msoptional integerfalls to globalyesPer-queue cap on the policy retry delay.
max_payload_bytesoptional integerfalls to globalyesPer-queue payload cap.
allowed_encodingsoptional array of stringsfalls to globalyesPer-queue encoding allowlist.
allowed_job_typesoptional array of stringsnone (allow all)yesPer-queue job type allowlist. Queue-only — there is no global equivalent.
max_schedule_horizon_msoptional integerfalls to globalyesPer-queue scheduling horizon.
max_custom_entriesoptional integerfalls to globalyesPer-queue custom entry limit.
max_custom_total_bytesoptional integerfalls to globalyesPer-queue custom byte limit.
max_custom_key_bytesoptional integerfalls to globalyesPer-queue key byte limit.
dedup_window_msoptional integerfalls to globalrestart-onlyPer-queue deduplication window. Changing this value or adding/removing a per-queue dedup_window_ms override requires a restart.
max_queue_depthoptional integerfalls to globalyesPer-queue depth cap (tri-state: omit/0/number).

Per-queue effective limits

When a queue has no explicit override, the global [limits] value applies. When an override is set, it replaces the global for that queue only. The merged effective limits are validated at load time: default_max_attempts must not exceed max_attempts_ceiling, and max_payload_bytes must not exceed max_message_bytes.

[[queues]]
name = "emails"
default_priority = 2
max_payload_bytes = 1048576

[[queues]]
name = "thumbnails"
max_lease_duration_ms = 300000
dedup_window_ms = 3600000

Environment variable mapping

Every scalar config field can be set via an environment variable. The mapping rule is:

SEPP_<SECTION>__<FIELD>=<value>

The prefix SEPP_ is stripped and the __ (double underscore) separates the TOML section name from the field name. Values are parsed according to the field's type. Environment variables take precedence over the file, which takes precedence over built-in defaults.

Environment variableConfig path
SEPP_SERVER__LISTEN_ADDR=0.0.0.0:6000server.listen_addr
SEPP_SERVER__STRICT_QUEUES=trueserver.strict_queues
SEPP_STORAGE__PERSIST_MODE=bufferstorage.persist_mode
SEPP_METRICS__PROMETHEUS_LISTEN_ADDR=127.0.0.1:9464metrics.prometheus_listen_addr
SEPP_ADMIN__SESSION_TTL_MS=86400000admin.session_ttl_ms

Keep structured values like [[queues]] entries, [auth] api_keys and [admin] keys in the sepp.toml file. The env syntax can technically express them (SEPP_AUTH__API_KEYS='[{name="w",key="..."}]') but this is unsupported. An env-supplied auth.api_keys also pins the list, so the admin UI's key management rejects every change with env_pinned.

The environment variable SEPP_CONFIG is reserved: it sets the path to the config file itself, not a config key. Fields pinned by environment variables override any file value and are shown as locked in the admin UI editor.

Cross-validation rules

The following rules are checked when the config is loaded and on every hot-reload. If any check fails the entire new config is rejected and the server keeps running the previous valid configuration.

RuleScope
tls_cert_path and tls_key_path must both be set or both unset.[server], [admin]
max_payload_bytes must not exceed max_message_bytes.[limits] (and all [[queues]])
default_max_attempts must not exceed max_attempts_ceiling.[limits] (and all [[queues]])
retry_delay_ms must not exceed retry_delay_max_ms.[limits] (and all [[queues]])
max_queue_name_bytes must be between 1 and 65535.[limits]
Queue names must be valid (no empty, ".", "..", /, or control characters) and unique.[[queues]]
Queue names must not exceed limits.max_queue_name_bytes.[[queues]]
api_keys entries must have non-empty, unique names and non-empty, unique secrets.[auth]
Admin UI on a non-loopback address requires keys to be set.[admin]
Admin keys entries must have non-empty, unique names and non-empty, unique secrets.[admin]
session_ttl_ms must be between 60000 and 31536000000.[admin]
stats_history_ms must be between 60000 and 21600000.[admin]
When tracing.enabled is true, service_name must be non-empty.[tracing]
When metrics.enabled is true, otlp_endpoint must be non-empty and export_interval_ms must be > 0.[metrics]

See also

On this page