How to Set Up Alerts and Monitoring for Data Pipeline Failures in Kestra: A Complete Guide

Kestra provides built-in event-driven hooks and Prometheus metrics that let you detect pipeline failures instantly and send alerts to Slack, email, or webhooks without external monitoring tools.

The DataTalksClub/data-engineering-zoomcamp repository demonstrates production-grade observability patterns using Kestra's native notification plugins and metrics endpoints. To set up alerts and monitoring for data pipeline failures in Kestra, you configure onFailure hooks in your flow definitions, enable Prometheus scraping on the server, and route notifications through built-in plugins that execute automatically when tasks fail.

Understanding Kestra's Three-Layer Monitoring Architecture

Kestra's monitoring stack operates through three distinct layers that work together to provide complete visibility into your data pipelines.

Health-Check and Metrics Layer

The Kestra server exposes Prometheus metrics at /actuator/prometheus and a health endpoint at /actuator/health. These endpoints allow continuous visibility into server status and performance. You can scrape these metrics using any Prometheus instance and visualize them in Grafana to track system-level health.

Failure Detection via Event Hooks

Every workflow run emits lifecycle events (RUNNING, SUCCESS, FAILED, KILLED). Kestra detects failures by hooking into these events using Triggers or Listeners defined directly in your flow YAML. This event-driven architecture ensures immediate detection when any task or workflow fails.

Alert Delivery with Notification Plugins

Kestra ships with dedicated notification plugins that push alerts to external systems. Available plugins include io.kestra.plugin.notifications.slack.SlackWebhook, io.kestra.plugin.notifications.email.Email, and io.kestra.plugin.notifications.webhook.Webhook. These execute from an onFailure section of a flow or from dedicated notification tasks that run only when parent tasks fail.

Configuring Failure Alerts with onFailure Hooks

The onFailure block in Kestra flows runs only when the parent task throws an exception. This pattern keeps alert logic version-controlled and testable alongside your pipeline code.

Slack Alert Configuration

The following example from 02-workflow-orchestration/flows/02_python.yaml demonstrates sending a Slack notification when a Python script fails:

id: python_example
namespace: data_zoomcamp
tasks:
  - id: run_script
    type: io.kestra.plugin.scripts.python.Script
    script: |
      import time, random
      time.sleep(2)
      if random.random() > 0.5:
          raise Exception("Random failure")
    onFailure:
      - id: slack_alert
        type: io.kestra.plugin.notifications.slack.SlackWebhook
        webhookUrl: "{{ secret('SLACK_WEBHOOK_URL') }}"
        message: |
          :warning: *Kestra flow failed*  
          • Flow: `{{ flow.id }}`  
          • Task: `{{ task.id }}`  
          • Run ID: `{{ run.id }}`  
          • Error: `{{ task.errors }}`  

The {{ secret('SLACK_WEBHOOK_URL') }} expression pulls the webhook URL from Kestra's secret store, keeping credentials out of version control.

Email Alert Configuration

For teams preferring email notifications, use the built-in SMTP plugin:

tasks:
  - id: extract_data
    type: io.kestra.plugin.jdbc.postgresql.Query
    sql: SELECT * FROM raw.taxi
    onFailure:
      - id: email_alert
        type: io.kestra.plugin.notifications.email.Email
        host: smtp.gmail.com
        port: 587
        username: "{{ secret('SMTP_USER') }}"
        password: "{{ secret('SMTP_PASS') }}"
        from: "kestra@yourdomain.com"
        to:
          - "data-eng@example.com"
        subject: "[Kestra] {{ flow.id }} failed"
        body: |
          The task `{{ task.id }}` in flow `{{ flow.id }}` failed.
          Run ID: {{ run.id }}
          Error details:
          {{ task.errors }}

Enabling Prometheus Metrics and Grafana Dashboards

After starting Kestra with Docker Compose using the repository's docker-compose.yml, enable the Prometheus exporter by setting the environment variable:


# 02-workflow-orchestration/docker-compose.yml

services:
  kestra:
    image: kestra/kestra:latest
    ports:
      - "8080:8080"
    environment:
      - KESTRA_SERVER_METRICS_ENABLED=true

Scrape http://localhost:8080/actuator/prometheus from your Prometheus server. Import the official Kestra Grafana dashboard to visualize run counts, failure rates, and task-level latency metrics.

Building Reusable Alert Flows for Centralized Management

For larger deployments, route all failure events to a single webhook that forwards to PagerDuty, Opsgenie, or custom incident-response services. Define a reusable notification flow and call it from any other flow's onFailure using the io.kestra.plugin.core.flow.Trigger task.

Create a centralized alert forwarder:


# flows/alert_forwarder.yaml

id: alert_forwarder
namespace: shared
tasks:
  - id: forward
    type: io.kestra.plugin.notifications.webhook.Webhook
    url: "{{ secret('ALERT_WEBHOOK_URL') }}"
    method: POST
    headers:
      Content-Type: application/json
    body: |
      {
        "flow": "{{ flow.id }}",
        "task": "{{ task.id }}",
        "runId": "{{ run.id }}",
        "status": "{{ task.state }}",
        "error": "{{ task.errors }}"
      }

Reference this from any other flow:

onFailure:
  - id: forward_failure
    type: io.kestra.plugin.core.flow.Trigger
    flowId: alert_forwarder

Summary

  • Kestra exposes Prometheus metrics at /actuator/prometheus and health checks at /actuator/health for infrastructure monitoring.
  • The onFailure hook executes notification tasks only when specific tasks fail, keeping alert logic co-located with pipeline definitions.
  • Built-in notification plugins like io.kestra.plugin.notifications.slack.SlackWebhook support Slack, email, and generic webhooks.
  • Reusable alert flows using io.kestra.plugin.core.flow.Trigger enable centralized incident management across multiple pipelines.
  • Secret management via {{ secret('KEY') }} expressions keeps credentials secure while maintaining Infrastructure-as-Code principles.

Frequently Asked Questions

How do I access Kestra's Prometheus metrics?

Configure your Prometheus server to scrape http://<kestra-host>:8080/actuator/prometheus after setting KESTRA_SERVER_METRICS_ENABLED=true in your environment variables. The endpoint exposes counters for workflow executions, task durations, and failure rates that you can visualize in Grafana dashboards.

Can I send alerts to multiple channels simultaneously?

Yes. Define multiple tasks within a single onFailure block, or create a dedicated notification flow that triggers multiple notification tasks in parallel. Each task can target a different channel (Slack, email, webhook) using the respective plugin types.

How do I secure webhook URLs and credentials in alert configurations?

Use Kestra's secret store with the {{ secret('KEY_NAME') }} expression syntax. This keeps sensitive values out of your YAML files while allowing the flow to access them at runtime. Store the actual values in Kestra's secrets management UI or through environment variables depending on your deployment mode.

What's the difference between onFailure and triggers for monitoring?

The onFailure hook runs within the same flow context immediately when a specific task fails, giving you granular control per task. Triggers (using io.kestra.plugin.core.flow.Trigger) listen for state changes across flows and can centralize alerting logic, making them ideal for platform teams managing multiple pipelines from a single notification service.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →