New to Kestra?
Use blueprints to kickstart your first workflows.
Check a GTFS-Realtime vehicle positions feed every five minutes for staleness and missing vehicles, and alert after repeated failures. Runs with no setup.
Transit apps show live arrival times from GTFS-Realtime feeds. When an agency's feed freezes or stops reporting vehicles, apps quietly fall back to the timetable and riders get times that look live but are not. This flow fetches a VehiclePositions feed every five minutes, checks how old it is and how many vehicles report a position, and alerts only after several unhealthy checks in a row, so one slow fetch does not page anyone.
It runs with no setup. The default feed is the MBTA's public vehicle positions feed, Slack is off and alerts do not fail the run.
download (io.kestra.plugin.core.http.Download) fetches the protobuf snapshot from feed_url.inspect (io.kestra.plugin.scripts.python.Script) decodes it with gtfs-realtime-bindings and outputs healthy, problems, feed_age_seconds, vehicles, vehicles_with_position and stale_vehicles. A feed is unhealthy when its header timestamp is older than max_age_seconds, has no timestamp, or fewer than min_vehicles vehicles report a position.previous_streak (io.kestra.plugin.core.kv.Get) reads the number of unhealthy checks in a row from the KV store.health_gate (io.kestra.plugin.core.flow.If) resets the streak to 0 on a healthy check and logs the numbers. On an unhealthy check it adds one to the streak.alert_gate alerts once the streak reaches alert_after: it posts to Slack when notify_slack is true and ends the run as FAILED when fail_on_alert is true. Below the threshold it logs a warning with the count so far.feed_url (STRING, default the MBTA vehicle positions feed): the GTFS-Realtime VehiclePositions URL.max_age_seconds (INT, default 120): the oldest acceptable feed header timestamp.min_vehicles (INT, default 1): the fewest vehicles that must report a position.alert_after (INT, default 2): unhealthy checks in a row before alerting.notify_slack (BOOL, default false): post alerts to Slack.fail_on_alert (BOOL, default false): end the run as FAILED on an alert.feed_url or the download task.SLACK_WEBHOOK_URL: Slack incoming webhook. Only needed when notify_slack is true.max_age_seconds set to 1 to see an unhealthy check. The first run logs a warning with the streak count, and a second run within the threshold reaches alert_after and alerts.feed_url at your agency's feed and adjust max_age_seconds to how often it publishes.every_five_minutes schedule on to keep checking.outputs.inspect.vars.healthy: true or false.outputs.inspect.vars.problems: what made the check unhealthy, or none.outputs.inspect.vars.feed_age_seconds, vehicles, vehicles_with_position, stale_vehicles: the numbers behind the check.