GUIDE · DAGSTER · SCHEDULES · FREE

Monitor Dagster schedules — alerts for failed and missed runs

Dagster schedules and sensors are submitted by the dagster-daemon. If that daemon stops — a crash, an OOM, a bad deploy — every schedule silently stops firing, and Dagster itself can't tell you, because nothing runs to raise the alarm. Attach a success and failure hook to your job and pair it with a LastPing monitor: failed runs page you immediately, and a run that never fires opens an incident on its own.


Setup: a success hook, a failure hook, a matching monitor

Hooks fire per run; the monitor's own schedule catches the daemon-down case.

Create a heartbeat monitor in LastPing

In the console, create a monitor with the same cron as your Dagster schedule. Set the grace window to the job's expected runtime plus a margin. Copy the ping URL.

https://ping.lastping.dev/<your-monitor-id>

Define success_hook and failure_hook

Hooks run in the run process and give you the run context. Ping on success, ping /fail on failure:

from dagster import success_hook, failure_hook, job, HookContext import requests PING = "https://ping.lastping.dev/<your-monitor-id>" @success_hook def ping_success(context: HookContext): requests.get(PING, timeout=10) @failure_hook def ping_failure(context: HookContext): requests.get(f"{PING}/fail", timeout=10)

Attach the hooks to the scheduled job

Apply both hooks to the job the schedule targets. They then fire on every run of that job:

@job(hooks={ping_success, ping_failure}) def nightly_assets(): build_report() # schedule that targets the job from dagster import ScheduleDefinition nightly_schedule = ScheduleDefinition( job=nightly_assets, cron_schedule="0 3 * * *", )

The daemon-down case needs no code

Because the LastPing monitor runs on its own schedule, a run that never submits — daemon down, code location failing to load, schedule toggled off — simply produces no ping, and the incident opens automatically. That's the failure Dagster's own alerting can't surface.


What this catches

  • Run fails — the failure_hook pings /fail; you're paged immediately.
  • dagster-daemon down — no schedule ticks, no ping arrives → incident opens.
  • Code location fails to load — the schedule can't submit; the missing check-in is caught.
  • Recovery — the next successful run closes the incident automatically.

Using Prefect instead? See Prefect flows. Airflow? See Airflow DAGs. Celery beat? See Celery. For the base pattern, see Monitor Python scripts.


Questions people ask

Front-loaded answers — the most important fact first.

  • Doesn't Dagster have its own alerting?

    Dagster+ has alert policies for run failures. Open-source Dagster relies on you writing run-failure sensors. Neither easily reports the failure that matters most — the dagster-daemon being down, which silently stops all schedules and sensors. A dead-man's-switch expects a check-in per scheduled run and opens an incident when one is missing.

  • Will this catch the daemon being down?

    Yes — that's the main reason to use it. If the daemon is down, no schedule ticks and no hook fires, so no ping is sent. The LastPing monitor's own schedule notices the missing check-in and opens an incident.

  • Hooks or a run-failure sensor?

    Hooks are simpler for the per-run success/fail signal and run inline with the job. A run-failure sensor is an alternative for the fail path but still runs inside Dagster, so it can't report a dead daemon. Combine hooks (for run outcome) with the LastPing schedule (for missed runs) to cover both.

  • Is this free?

    Yes. LastPing is free and fully hosted with no monitor cap and no paid tier. See vs Healthchecks.io and vs Cronitor.

FREE · FULLY HOSTED · NO PAID TIER

When the daemon dies, your schedules go quiet. Be told.

Two hooks and a matching monitor. First alert in under a minute — and LastPing monitors itself the same way.