Skip to content

Log Levels and Log Format

Log format

Every line is newline-delimited JSON (one complete JSON object per line of output) written to standard output. Every line carries "instance": N to tell apart the logs from multiple Processors running against the same database.

{"ts":"2026-06-01T12:00:00.123456789Z","level":"info","msg":"pg_relay started","workers":2,"instance":1}
{"ts":"2026-06-01T12:00:01.000234567Z","level":"debug","msg":"ok: order_placed, id: 42","instance":1}
{"ts":"2026-06-01T12:00:01.500123456Z","level":"warn","msg":"retry_scheduled: send_email, id: 43","instance":1}
{"ts":"2026-06-01T12:00:05.800234567Z","level":"error","msg":"error: send_email, id: 44","log_id":1234,"instance":1}

The payload is never logged — only correlation identifiers appear (the channel name, the queue ID, the log ID). This means you can ship Processor logs to any log aggregation system without any risk of leaking event data.

Log message reference

Message Level Visible at default (warn)? Extra fields
pg_relay started info no workers
pg_relay stopping info no
pg_relay stopped info no
pg_relay reconnected info no
instance_limit_reached error yes detail
preflight_ok debug no check, detail
preflight_warn warn yes check, detail
preflight_error error yes check, detail
ok: <ch>, id: <id> debug no
skipped: id: <id> debug no
expired: <ch>, id: <id> debug no
invalid: <ch>, id: <id> warn yes
retry_scheduled: <ch>, id: <id> warn yes
error: <ch>, id: <id> error yes log_id
max_retries_error: <ch>, id: <id> error yes log_id
post_process_error: <ch>, id: <id> error yes log_id
probe_error error yes error
pending_ids_error error yes error
process_error error yes error, id
reconnecting warn yes attempt, backoff_ms, error
pg_relay paused / pg_relay resumed info no — (logged once per transition)
pg_relay reloading / pg_relay reloaded info no
reload_failed error yes error (the Processor then exits with a non-zero status)
reload_requested: <ch>, id: <id> info no — (this instance processed a pg_relay.reload event)
notifier_detected info no detail (the registry re-check found the notifier newly installed)
notifier_unavailable warn yes detail (why 'notify' events cannot currently be served)
notifier_interface_unavailable warn yes registered_version, error
notify_withheld: id: <id> debug no — (left unclaimed, pending a registry re-check)
set_status_failed warn yes pk, status, error (the event still resolves)
debug_trace_unavailable / debug_trace_failed debug no error (tracing never affects the actual send)
outage_alert_fired warn yes transport, plus http_status for webhook (the out-of-band outage alert was delivered)
outage_alert_recovered warn yes transport, plus http_status for webhook (the recovery message was delivered; the episode resets)
outage_alert_failed warn yes kind (outage/recovery), transport, plus http_status or error — the error text never contains the endpoint URL
start_notify_sent / stop_notify_sent info no transport, plus http_status for webhook (the lifecycle notification was delivered)
start_notify_failed / stop_notify_failed warn yes transport, plus http_status or error (one attempt, best-effort; the Processor runs on / exits regardless)
notify_config_invalid error yes error (a lifecycle-notification contract is present but invalid; the Processor then refuses to start)
spool_config_invalid error yes error (a PG_RELAY_SPOOL_* size cap is present but not an integer; the Processor then refuses to start)
spool_dir_unavailable warn yes variable, path, error (at start: a directory named in the environment does not exist; its channel's events are withheld until it does)
spool_unavailable / spool_available warn / info yes / no channel, plus reason for unavailable (a file_spool channel's directory is not configured, missing, unwritable, or at its cap — logged once per transition; events are withheld, not failed)
spool_withheld: id: <id> debug no — (one file_spool event left pending because its directory is unavailable)
spool_exists: <ch>, id: <id> / spool_replaced: <ch>, id: <id> info no log_id (the file already existed: skipped as a redelivery, or overwritten under replace)

Continue to High Availability for how to run more than one Processor safely.