On 2026-11-05 nothing noticed ~360 EC2 launches in 38 minutes, or a run
waiting three hours for workers that never came. The scheduler evaluates
these rules every ORCA_WATCHDOG_SECONDS (60; 0 turns the watchdog off),
each from Postgres only (never object storage), with the thresholds below
(each rule's environment variable overrides its default):
| Rule |
Trips when |
Scope |
launches |
more than ORCA_WATCHDOG_LAUNCHES (200) instances were launched in the last hour (pool handovers aren't launches) |
all pipelines |
cost |
the estimated cost of the instances up (orca.fleet's price table) stayed over ORCA_WATCHDOG_COST_HOUR ($3) an hour for ORCA_WATCHDOG_COST_MINUTES (15) minutes, or the last 24 hours cost over ORCA_WATCHDOG_COST_DAY ($25) |
all pipelines |
idle |
at least ORCA_WATCHDOG_IDLE_WORKERS (4) workers, up for ORCA_WATCHDOG_IDLE_MINUTES (10, at most 30) minutes, averaged under ORCA_WATCHDOG_IDLE_CPU (15) percent CPU over them (pooled idle and draining workers aren't counted) |
the pipelines owning those workers |
failing |
a pipeline had more than ORCA_WATCHDOG_FAILED (20) failed attempts in the last hour, or at least ORCA_WATCHDOG_FAILED_MIN (10) attempts ended and more than ORCA_WATCHDOG_FAILED_PERCENT (50) percent failed |
each such pipeline |
stuck |
a run with a running attempt, on instances that are sampled, has had no attempt start or end, no instance launched or ended and no sampled host over ORCA_WATCHDOG_STUCK_CPU (5) percent CPU for ORCA_WATCHDOG_STUCK_MINUTES (30, at most 30, since samples are kept that long) minutes |
that run's pipeline |
control |
the control instance's newest minute has memory over ORCA_WATCHDOG_MEMORY (90) percent or its fullest disk over ORCA_WATCHDOG_DISK (85) |
all pipelines |
A tripped rule pauses its scope through orca.pause.set_paused
(what the UI's Pause button does; pipelines already paused are left
alone), writes an orca.audit row per pipeline (user watchdog, the
rule's numbers), and a row of orca.watchdog_trips, which the banner on
/, /ops/pools and /ops/control, /watchdog and /metrics show for as long as any of its
pipelines is paused. It never resumes anything. A rule that is still over
its limit when a pipeline is unpaused trips again on the next pass, so
snooze it (orca watchdog snooze <rule> 2h, or on /watchdog) first;
that is stored in orca.watchdog_rules and audited.
A rule checks one threshold or more (limits: control checks memory
and disk, cost the sustained rate and the day, failing the count and
the share, idle the CPU and the number of workers). Each reading keeps
every check's value and limit and whether it is past it, and so does each
trip, so orca watchdog status, /watchdog and /api/watchdog show
every threshold and which one tripped.
Evaluation is pure (eval_*, over plain rows) apart from the gathering
(gather_*).
Structs
Config
struct Config
Implements Copyable, Movable
- Fields
seconds: Float64launches: Intcost_hour: Float64cost_minutes: Intcost_day: Float64idle_cpu: Float64idle_minutes: Intidle_workers: Intfailed: Intfailed_percent: Float64failed_min: Intstuck_minutes: Intstuck_cpu: Float64memory: Float64disk: Float64control_price: Float64: Dollars an hour of the control instance (ORCA_CONTROL_TYPE), or 0.fixed_price: Bool: The runner launches no instances (ORCA_RUNNER=local), so the cost rule has nothing to price: it reads "fixed price" and never trips.
Check
struct Check
One threshold a rule checks, and what it saw against it.
Implements Copyable, Movable
- Fields
name: Stringvalue: Float64: -1 when there is nothing to judge.limit: Float64unit: Stringop: String: How the value trips it: over, under or at least the limit.past: Bool: The value is past the limit (the rule trips when all of its conditions are; for idle both checks must be past).
Reading
struct Reading
What a rule saw: its current value against its threshold, and if that is a trip, why and which pipelines.
Implements Copyable, Movable
- Fields
rule: Stringvalue: Float64: -1 when there is nothing to judge (no samples).threshold: Float64: The limit of the check nearest it (value is that check's).tripped: Booldetail: Stringpipelines: List[String]checks: List[Check]: Every threshold the rule checks (limits), with its value.
Lease
struct Lease
An instance's row: its type, how long ago it started and ended (-1: it hasn't).
Implements Copyable, Movable
- Fields
instance_type: Stringstart_ago: Float64end_ago: Float64
Counts
struct Counts
A pipeline's attempts that ended in the last hour.
Implements Copyable, Movable
- Fields
pipeline: Stringfailed: Inttotal: Int
Quiet
struct Quiet
A run with a running attempt, and the minutes nothing has moved.
Implements Copyable, Movable
- Fields
pipeline: Stringrun: Intminutes: Float64
Trip
struct Trip
Implements Copyable, Movable
- Fields
rule: Stringago: Float64at: Stringvalue: Float64threshold: Float64detail: Stringpipelines: List[String]: The pipelines it paused that are still paused.id: Intacked_by: String: Who kept it paused (acknowledged it), or empty.checks: List[Check]: The checks as the trip saw them (empty for a trip from before they were kept).
RuleRow
struct RuleRow
Implements Copyable, Movable
- Fields
rule: Stringvalue: Float64threshold: Float64checked: Boolsnoozed_until: String: UTC, or empty.snoozed_by: Stringtripped: Boolnote: String: Why the rule has no reading ("fixed price"), or empty.checks: List[Check]: Each threshold with its last value (-1 before the first check).tripped_on: List[String]: The checks its unacknowledged trips tripped on (what tripped shows).