GUIDE · PREFECT · FLOWS · FREE

Monitor Prefect flows — alerts for failed and missed flow runs

Prefect gives you rich state tracking inside the UI — but its worst failure is invisible to anything running inside Prefect: if the worker or work pool is down, scheduled flow runs never enter a Running state, so an in-flow notification never fires. Add a dead-man's-switch with two state hooks and LastPing alerts you when a run fails and when a run that should have happened never did.


Setup: two state hooks on your flow

Ping on completion, ping /fail on failure. A matching monitor schedule catches missed runs.

Create a heartbeat monitor in LastPing

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

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

Add on_completion / on_failure hooks

State hooks receive (flow, flow_run, state) and run in the flow process. Ping on success, ping /fail on failure:

from prefect import flow import httpx PING = "https://ping.lastping.dev/<your-monitor-id>" def ping_success(flow, flow_run, state): httpx.get(PING, timeout=10) def ping_failure(flow, flow_run, state): httpx.get(f"{PING}/fail", timeout=10) @flow(on_completion=[ping_success], on_failure=[ping_failure]) def nightly_etl(): ... # your flow logic

Catch the "never started" case with the schedule

Because the LastPing monitor has its own schedule, a run that never starts — worker down, deployment paused, work pool empty — simply produces no ping, and the incident opens on its own. No code required for that path; it's the whole point of the dead-man's-switch.

Signal long flows with a start ping

For long ETL flows, add an on_running-style start ping to PING + "/start" at the top of the flow and set a tight grace window to detect a hung run before it blocks the next schedule.


What this catches

  • Flow run fails — the on_failure hook pings /fail; you're paged immediately.
  • Worker / work pool down — scheduled runs never start, no ping arrives → incident opens.
  • Deployment paused or schedule removed — silent in Prefect; caught by the missing check-in.
  • Recovery — the next successful flow run closes the incident automatically.

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


Questions people ask

Front-loaded answers — the most important fact first.

  • Can't Prefect already send failure notifications?

    Prefect Cloud automations can notify on a Failed state. But the failure that hurts most — a worker or work pool that's down, so scheduled runs never enter Running — can't be reported by anything running inside a flow, because no flow runs. A dead-man's-switch expects a check-in on every scheduled run and opens an incident when one is missing.

  • Does this work with self-hosted Prefect (open source)?

    Yes. State hooks are part of open-source Prefect and execute wherever the flow runs, so this works identically on self-hosted Prefect Server and on Prefect Cloud.

  • Should I ping from a hook or from inside the flow?

    Prefer hooks. on_completion fires only when the flow reaches a Completed state, so it won't ping success on a flow that failed partway. Pinging at the end of the flow body would be skipped by an exception — which is fine for the fail path, but hooks keep success and failure cleanly separated.

  • 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

A down worker means silent flows. Catch it.

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