Schedule icon
Download icon
Script icon
Get icon
If icon
Set icon
Log icon
SlackIncomingWebhook icon
Fail icon

Check that a GTFS-Realtime vehicle feed is fresh and alert when it goes stale

Check a GTFS-Realtime vehicle positions feed every five minutes for staleness and missing vehicles, and alert after repeated failures. Runs with no setup.

Categories
Data

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.

How it works

  1. download (io.kestra.plugin.core.http.Download) fetches the protobuf snapshot from feed_url.
  2. 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.
  3. previous_streak (io.kestra.plugin.core.kv.Get) reads the number of unhealthy checks in a row from the KV store.
  4. 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.
  5. 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.

Inputs

  • 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.

Prerequisites

  • A Kestra worker that can run Docker containers, for the Python script.
  • Network access to the feed URL. Some agencies require an API key in the URL or a header; add it to feed_url or the download task.

Secrets

  • SLACK_WEBHOOK_URL: Slack incoming webhook. Only needed when notify_slack is true.

Quick start

  1. Save the flow and run it with the defaults. The log shows the feed age and the number of vehicles with a position.
  2. Run it with 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.
  3. Point feed_url at your agency's feed and adjust max_age_seconds to how often it publishes.
  4. Leave the every_five_minutes schedule on to keep checking.

Expected outputs

  • 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.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.