Log icon
DiscordIncomingWebhook icon
RealtimeTrigger icon

React to MQTT Alarms in Real Time with Per-Message Executions

React to MQTT alarms in real time with Kestra. A realtime trigger starts one execution per message and posts topic and severity to Discord.

Categories
Infrastructure

Polling is the wrong shape for alarms. This blueprint uses io.kestra.plugin.mqtt.RealtimeTrigger to hold a live subscription on alarms/# and start one execution per message the instant it arrives, no interval, no batch, no polling gap. Each execution carries the message as trigger.* values: the flow logs the alarm for the audit trail and posts the source topic and severity to Discord, turning a device-side fault into an on-call notification in sub-second time.

How it works

  1. alarm_stream (io.kestra.plugin.mqtt.RealtimeTrigger) connects to the broker from the MQTT_SERVER secret and subscribes to the alarms/# wildcard. Unlike the plugin's polling trigger, the realtime trigger keeps the subscription open and fires per message, so reaction time is bounded by the broker, not by an interval.
  2. Each execution exposes the message directly: {{ trigger.topic }} names the exact subtopic that raised the alarm, and because serdeType: JSON parses the payload, individual fields such as {{ trigger.payload.severity }} are addressable as scalars. The trigger also exposes id, qos, and retain per message.
  3. log_alarm writes the topic and payload fields into the execution logs, giving every alarm a searchable record.
  4. alert_discord posts the topic, severity, device id, and detail to Discord as plain scalars.
  5. The errors block posts a distinct Discord alert when handling fails, so a broken reactor is itself alarmed.
  6. The trigger ships disabled: true; enable it once the broker secret is in place.

What you get

  • Sub-second reaction to device alarms with one execution per message, each individually retryable and auditable.
  • Topic-aware alerting: the wildcard subscription means one flow covers every device publishing under alarms/.
  • Parsed JSON payloads, so severity-based routing is a template expression away.
  • A failure alert covering the reactor itself, closing the "who watches the watcher" gap.

Who it's for

  • IoT and OT teams whose devices already publish faults to MQTT and need them in a chat channel now.
  • On-call engineers replacing a homegrown bridge daemon between the broker and their alerting stack.
  • Teams that want per-alarm execution history instead of grepping a consumer's stdout.

Why orchestrate this with Kestra

A bridge script that subscribes and forwards to a webhook works until it crashes at 3 a.m. with nobody watching. Kestra runs the subscription as a supervised trigger, records every alarm as an execution with logs and timings, retries the notification on transient failures, and alerts when handling breaks. Adding a second reaction, such as opening a ticket or publishing a command back to the device, is one more task in the same flow.

Prerequisites

  • An MQTT broker reachable from Kestra with devices publishing JSON alarms under alarms/#, e.g. payloads like {"severity": "critical", "device_id": "dev-001", "detail": "overheat"}. Public test brokers accept anonymous connections; for authenticated brokers, add the username and password properties to the trigger from secrets.
  • A Discord incoming webhook for alerts.

Secrets

  • MQTT_SERVER: broker URI, e.g. tcp://broker.example.com:1883.
  • DISCORD_WEBHOOK_URL: Discord incoming webhook URL.

Quick start

  1. Add the MQTT_SERVER and DISCORD_WEBHOOK_URL secrets to your Kestra namespace.
  2. Set disabled: false on the alarm_stream trigger and save the flow.
  3. Publish a test alarm, e.g. mosquitto_pub -t alarms/dev-001 -m '{"severity": "critical", "device_id": "dev-001", "detail": "overheat"}'.
  4. Confirm an execution starts immediately and the Discord message names the topic and severity.

How to extend

  • Branch on severity with io.kestra.plugin.core.flow.If, paging only on critical and logging the rest.
  • Publish an acknowledgment or remediation command back to the device with this plugin's Publish task.
  • Open an incident in your ticketing system alongside the Discord post.
  • Prefer batched handling for lower-urgency topics with the plugin's polling trigger or the telemetry batch collector blueprint.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.