Skip to content

System Events

System events are structured signals emitted by superd when something meaningful happens in the cluster. They power licensed notifications (notify.toml, notify plugin), the audit log (security plugin), and OSS event hooks ([[event_hooks]]).

This page is the canonical list of all event types. Configuration for reacting to events differs by mechanism — see Where to configure reactions.

Event catalog

Event nameRust variantWhen it firesPayload fields
process_startedProcessStartedProcess spawned successfully and received a PIDprogram_id, program_name, pid
process_fatalProcessFatalProcess stopped and will not auto-restart (retries exhausted, manual fatal, spawn/pre-start failure, cron failure, OTA rollback trigger, etc.)program_id, program_name, pid, uptime_secs, exit_code, msg, log_tail
process_backoffProcessBackoffProcess crashed but will retry (autorestart still active)program_id, program_name, pid, uptime_secs, exit_code, retry_count
process_recoveredProcessRecoveredProcess was unstable (backoff/fatal path) and is now Healthy againprogram_id, program_name, pid, uptime_sec
system_startupSystemStartupsuperd manager loop started (after loading programs)hostname
system_shutdownSystemShutdownsuperd is shutting down gracefully(none)

Notes

  • process_fatal + log_tail: Licensed webhooks (notify plugin) can attach the last lines of stderr when include_log_tail = true on a channel. The tail is read at event time from the program log file.
  • process_recovered: Only emitted after a prior crash/backoff (alert_pending_recovery). A clean first start does not emit recovery.
  • Health check failures alone do not emit a dedicated event today. A failing health check keeps status at Running; repeated process exits still emit process_backoff / process_fatal.
  • Cron jobs: exit 0 → stopped quietly; non-zero exit → process_fatal.

JSON shape (internal)

Events are serialized with an internally tagged enum:

{
  "type": "ProcessFatal",
  "payload": {
    "program_id": "550e8400-e29b-41d4-a716-446655440000",
    "program_name": "web-server",
    "exit_code": 137,
    "msg": "Stopped after 3 retries.",
    "log_tail": "Error: bind: Address already in use\n"
  }
}

Licensed webhook envelopes wrap this in a richer outer object (summary, markdown, system, etc.). See Event Notifications.

Where to configure reactions

MechanismConfig locationScopeRequiresStatus
Lifecycle hooks[[programs]][programs.hooks]Per program, tied to start/stop flowOSS✅ Implemented — see Lifecycle Hooks
Webhook notificationsconf/notify.toml[[channels]]Global channels, filter by triggers💎 notify plugin✅ Implemented
Event hookssuper.toml[[event_hooks]]Global, filter by events + programsOSS✅ Implemented — see Event Hooks
[webhook] in super.toml[webhook]⚠️ Parsed only, not wired — see Config Reference
Rust Extension::on_eventCompile-time or licensed pluginGlobalPlugin / custom build✅ Implemented

Current layout (today)

super.toml                    # daemon + [[programs]] + per-program hooks
├── [server]
├── [storage] / [logging]
├── [webhook]                 # ⚠ reserved — ignored at runtime
└── [[programs]]
    └── [programs.hooks]      # pre_start / post_start / pre_stop / post_stop

conf/notify.toml              # notify plugin — [[channels]] + triggers
snapshot.json                 # persisted program state (includes hooks from API/stack)

Lifecycle hooks live per program because they run inside that program’s start/stop pipeline.

System event reactions (webhooks, event hooks) are global — one listener handles events from any program, with optional name filters.

Supervisor mapping

Supervisor [eventlistener]Super
PROCESS_STATE_RUNNINGprocess_started
PROCESS_STATE_EXITEDprocess_backoff or process_fatal (depends on autorestart)
PROCESS_STATE_FATALprocess_fatal
TICK_60Not supported

See also vs Supervisor.