PulseWatchPulsewatch

Job dependencies and chains

Cron jobs are implicitly ordered, and nothing else in monitoring models that. Tell PulseWatch the order and one broken job stops producing three confusing alerts.

The problem, concretely

Extract at 02:00, transform at 03:00, load at 04:00. Extract fails. Two things can happen and neither is what you want:

text
02:00  extract    FAILS          -> alert (correct)
03:00  transform  runs anyway     -> "up"  (lying: it read yesterday's data)
04:00  load       runs anyway     -> "up"  (lying)

               ...or, if they fail too:

02:00  extract    FAILS          -> alert
03:00  transform  FAILS          -> alert (no cause of its own)
04:00  load       FAILS          -> alert (no cause of its own)

Three green monitors where one is broken, or three alerts for one problem. Declaring the dependency fixes both.

Declaring one

On the monitor page, under Depends on, pick the upstream monitor and a mode. A monitor can have up to 10 upstreams, and a chain can be up to 10 deep. Loops are rejected, including indirect ones, and the error names the path.

ModeWhat it means
Must have succeeded recently
require_success
The upstream must have succeeded inside a freshness window you choose. The default, and the only mode that catches a job succeeding on old data.
Must not be down or warning
require_healthy
The upstream simply must not be in down or warn right now. Makes no claim about how fresh its output is.
Show context only
advisory
Never changes this monitor’s state. The upstream still appears on alerts and on the monitor page.

A dependent that fails goes blocked, not down

When the upstream is broken, the dependent's failure has no cause of its own, so paging about it points at the wrong system. Blocked is a real state:

  • It is not downtime and opens no incident.
  • It does not page.
  • It is excluded from the uptime percentage entirely: not counted as available either, because scoring it would charge a service for its dependency's outage.
  • On the dashboard it nests under whatever blocked it, rather than looking like a separate failure.

The upstream's alert is the one that goes out, and it names what it took with it:

text
🔴 extract-daily is down
reason: no_ping

3 downstream jobs blocked: transform-daily, load-warehouse, refresh-dashboards.

A dependent that succeeds on stale data gets a warning

This is the case the feature exists for, and the one that is invisible without it. The job ran. It reported success. Every dashboard is green. And the numbers it just wrote are yesterday's.

Under require_success, a successful run whose upstream has not succeeded inside the freshness window becomes a warning with reason stale_upstream. Like every warning it does not page: it appears in the daily digest and on the monitor page.

What does not warn: an upstream that is down right now but succeeded a minute ago. It left good data behind, and the dependent that read it is genuinely fine. Warning there would train you to ignore the warning that matters.

Leaving blocked

When the upstream recovers, the dependent resumes normal evaluation and its next clean ping returns it to up. No alert is sent for the blocked period.

If the upstream recovers and the dependent is still overdue, it goes down normally and alerts. That is not a late alert for the blocked time. It is the correct alert now that the excuse is gone. Blocked is never a place a job can hide.

The freshness window

Freshness is measured against the upstream's last successful run, deliberately not its last ping. A job calling /fail every five minutes has a very recent last ping and has produced nothing: measuring against that would read as perfectly fresh to everything downstream.

A warn run counts as a success here. It completed and wrote its output; refusing to count it would block a whole chain over one skipped file.

A paused upstream never blocks anything. Pausing a monitor is a decision to stop watching it, not a decision to stop watching everything downstream of it.