New to Kestra?
Use blueprints to kickstart your first workflows.
Detect silent device fleets with Kestra. Listen for MQTT heartbeats on a schedule, alert Discord and fail the run when no messages arrive.
Alarms tell you when devices complain; nothing tells you when they stop talking. This blueprint inverts the usual alerting direction: on a schedule, io.kestra.plugin.mqtt.Subscribe listens on heartbeat/+ for a short bounded window, and the flow treats an empty result as the incident. Zero heartbeats means a Discord alert and a deliberately failed execution, so fleet silence is red in the executions view instead of an unremarkable green run that collected nothing.
listen_heartbeats (io.kestra.plugin.mqtt.Subscribe) connects to the broker from the MQTT_SERVER secret and subscribes to heartbeat/+, where the single-level wildcard matches one heartbeat subtopic per device.maxDuration: PT15S caps the wait on a silent topic and maxRecords: 100 ends the task early on a healthy, chatty fleet. Either way the task completes and exposes messagesCount.check_fleet (io.kestra.plugin.core.flow.If) branches on {{ outputs.listen_heartbeats.messagesCount == 0 }}.alert_silent_fleet posts to Discord naming the window, then fail_execution (io.kestra.plugin.core.execution.Fail) marks the execution failed so dashboards, SLAs, and failure-based alerting all see it.log_heartbeat_count records the count and the execution ends green.errors block posts a Discord alert on any failed execution, covering both detected silence and a monitor that could not reach the broker; the two alerts are worded so the channel can tell them apart.Schedule trigger runs the check every 10 minutes.Detecting absence needs something that runs on a clock, remembers what it saw, and escalates. Kestra provides the schedule, the bounded Subscribe window, the branch that turns zero into failure, and the alert, all in one declarative file. The failed execution integrates with everything else that watches Kestra, so fleet silence propagates to the same place as any other pipeline failure.
heartbeat/<device_id> at an interval shorter than the check cadence, so a healthy window always contains at least one message. Public test brokers accept anonymous connections; for authenticated brokers, add the username and password properties to the task from secrets.MQTT_SERVER: broker URI, e.g. tcp://broker.example.com:1883.DISCORD_WEBHOOK_URL: Discord incoming webhook URL.MQTT_SERVER and DISCORD_WEBHOOK_URL secrets to your Kestra namespace.mosquitto_pub -t heartbeat/dev-001 -m '{"status": "alive"}', and confirm the execution ends green with a logged count.disabled: false on the every_10_minutes trigger and align maxDuration with your fleet's heartbeat interval.{{ outputs.listen_heartbeats.uri }} and diffing against a device registry.