How to Set Up Alerts and Scheduled Reports in Apache Superset: Email, Slack, and Webhook Configuration

Apache Superset enables automated alerts and scheduled reports through Celery workers that evaluate SQL thresholds or capture dashboard snapshots and dispatch notifications via the EmailNotification, SlackNotification, or WebhookNotification classes.

Setting up alerts and scheduled reports in Apache Superset requires configuring the underlying notification infrastructure and defining ReportSchedule objects that specify when and where to send data. This guide covers the complete implementation path from feature flags to production deployment, referencing the actual source code in the apache/superset repository.

Core Architecture and Data Models

All scheduling logic resides in superset/reports/models.py. The ReportSchedule ORM class stores the crontab expression, SQL query (for alerts), and references to charts or dashboards. Recipients are modeled separately through the ReportRecipient class, which uses the ReportRecipientType enumeration to distinguish channels:

class ReportRecipientType(StrEnum):
    EMAIL = "Email"
    SLACK = "Slack"
    SLACKV2 = "SlackV2"
    WEBHOOK = "Webhook"

# source: superset/reports/models.py#L65-L70

Each recipient record stores a JSON recipient_config_json field containing the target address, channel name, or webhook URL.

Alert Evaluation Logic

For threshold-based alerts, Superset executes the AlertCommand class defined in superset/commands/report/alert.py. The run() method evaluates the SQL query and applies a validator—either NOT_NULL or OPERATOR—to determine if the alert triggers:

if self._is_validator_not_null:
    self._report_schedule.last_value_row_json = str(self._result)
    is_null_or_nan = self._result is None or pd.isna(self._result)
    triggered = bool(self._result != 0 and not is_null_or_nan)
else:
    # operator validator

    triggered = OPERATOR_FUNCTIONS[operator](self._result, threshold)

# source: superset/commands/report/alert.py#L83-L95

When triggered is True, the execution pipeline proceeds to the notification phase.

Notification Channel Configuration

Superset dispatches messages through three primary notification classes located in superset/reports/notifications/. Each requires specific backend configuration.

Email Notifications

The EmailNotification class in superset/reports/notifications/email.py constructs HTML emails with optional CSV or PDF attachments. It relies on the SMTP helper send_email_smtp from superset/utils/core.py.

Required configuration in superset_config.py:

SMTP_HOST = "smtp.example.com"
SMTP_PORT = 587
SMTP_USER = "[email protected]"
SMTP_PASSWORD = "your_secure_password"
MAIL_DEFAULT_SENDER = "[email protected]"
EMAIL_REPORTS_SUBJECT_PREFIX = "[Superset Report]"  # default defined in superset/config.py#L1976

The subject line is generated dynamically:

def _get_subject(self) -> str:
    return __(
        "%(prefix)s %(title)s",
        prefix=current_app.config["EMAIL_REPORTS_SUBJECT_PREFIX"],
        title=self._name,
    )

# source: superset/reports/notifications/email.py#L204-L208

Slack Notifications

The SlackNotification class in superset/reports/notifications/slack.py supports the legacy Slack Web API. It uploads files or posts messages using the Slack SDK client retrieved from superset/utils/slack.py.

Configuration in superset_config.py:

SLACK_API_TOKEN = "xoxb-your-bot-token"

The token requires chat:write and files:write scopes. The notification logic handles file uploads versus simple messages:

client = get_slack_client()
channel = self._get_channel()
if files:
    client.files_upload(..., filetype=file_type)
else:
    client.chat_postMessage(channel=channel, text=body)

# source: superset/reports/notifications/slack.py#L99-L113

Enable the SLACK_V2_API feature flag to use the newer SlackNotificationV2 implementation, which is recommended for new installations.

Webhook Notifications

The WebhookNotification class in superset/reports/notifications/webhook.py posts JSON payloads to external HTTP endpoints. This channel requires explicit feature flag activation.

Enable in superset_config.py:

FEATURE_FLAGS = {
    "ALERT_REPORT_WEBHOOK": True,
}

For security, enforce HTTPS-only endpoints:

ALERT_REPORTS_WEBHOOK_HTTPS_ONLY = True  # default in superset/config.py

The implementation constructs a POST request:

wh_url = self._get_webhook_url()
response = requests.post(wh_url, json=payload, timeout=60)

# source: superset/reports/notifications/webhook.py#L24-L27

If the feature flag is disabled, the system raises NotificationUnprocessableException when attempting to create webhook recipients.

Step-by-Step Implementation Guide

Enable Required Feature Flags

Add the following to your superset_config.py to unlock all notification channels:

FEATURE_FLAGS = {
    "ALERT_REPORT_WEBHOOK": True,      # Enable webhook notifications

    "SLACK_V2_API": True,             # Use modern Slack API

    "ALERT_REPORTS": True,            # Enable the reporting feature itself

}

Configure Backend Services

Ensure your Celery workers are running with the beat scheduler enabled, as the reporting engine relies on periodic tasks defined in superset/tasks/scheduler.py.

Configure SMTP and Slack tokens as shown in the previous sections, then restart the Superset workers to load the new configuration.

Create Alerts and Reports via UI

  1. Navigate to SettingsAlerts & Reports.
  2. Click + Report or + Alert.
  3. Configure the Schedule using a crontab expression (e.g., 0 9 * * 1-5 for 9 AM weekdays).
  4. For Alerts, provide the SQL query and threshold logic.
  5. Add Recipients by selecting the channel type (Email, Slack, or Webhook) and entering the target address or URL.

Programmatic Creation via Python API

For infrastructure-as-code deployments, create schedules directly using the Superset ORM:

from superset.models.core import Database
from superset.reports.models import ReportSchedule, ReportRecipient, ReportRecipientType
from superset import db

# Retrieve target database

db_obj = db.session.query(Database).filter_by(database_name="production").one()

# Create the schedule

schedule = ReportSchedule(
    type="Alert",
    name="Revenue Drop Alert",
    crontab="0 */6 * * *",  # Every 6 hours

    sql="SELECT SUM(revenue) FROM daily_metrics WHERE dt = CURRENT_DATE - 1",
    validator_type="operator",
    validator_config_json='{"op":"<","threshold":50000}',
    database=db_obj,
    active=True,
)
db.session.add(schedule)
db.session.commit()

# Attach email recipient

email_recipient = ReportRecipient(
    type=ReportRecipientType.EMAIL,
    recipient_config_json='{"target":"[email protected]"}',
    report_schedule=schedule,
)
db.session.add(email_recipient)
db.session.commit()

Execution Flow and Celery Integration

Understanding the backend execution helps debug delivery failures. When a schedule fires, the following occurs:

  1. Celery Beat reads the crontab field from ReportSchedule and enqueues a task defined in superset/tasks/scheduler.py.
  2. The worker executes execute_report_schedule (defined in superset/commands/report/execute.py), which loads the schedule and creates a ReportExecutionContext.
  3. If schedule.type == "Alert", the system instantiates AlertCommand from superset/commands/report/alert.py to evaluate the SQL query against the configured validator.
  4. Upon successful execution, the system generates a ReportExecutionResult containing screenshots, CSV data, or PDF attachments.
  5. The notification manager iterates over schedule.recipients and instantiates the appropriate notification class (EmailNotification, SlackNotification, or WebhookNotification) to dispatch the payload.

Testing and Debugging Notifications

Before deploying to production, validate your configuration using Superset's Python shell:

Test Email Delivery

from superset.reports.notifications.email import EmailContent, EmailNotification
from superset.reports.models import ReportRecipient, ReportRecipientType

content = EmailContent(
    body="Test alert: Revenue threshold exceeded",
    name="Revenue Alert",
    url="https://superset.example.com/chart/123",
)

recipient = ReportRecipient(
    type=ReportRecipientType.EMAIL,
    recipient_config_json='{"target":"[email protected]"}',
)

notification = EmailNotification(content, recipient)
notification.send()

Test Slack Integration

from superset.reports.notifications.slack import SlackNotification
from superset.reports.models import ReportRecipient, ReportRecipientType

recipient = ReportRecipient(
    type=ReportRecipientType.SLACK,
    recipient_config_json='{"target":"#test-channel"}',
)

notification = SlackNotification(content, recipient)
notification.send()

Verify Alert Logic

Test your SQL threshold logic without triggering notifications:

from superset.commands.report.alert import AlertCommand
from superset.reports.models import ReportSchedule
import uuid

schedule = db.session.get(ReportSchedule, 42)  # Your alert ID

command = AlertCommand(schedule, uuid.uuid4())
triggered, message = command.run()
print(f"Triggered: {triggered}, Message: {message}")

Summary

  • Alerts execute SQL queries against thresholds using AlertCommand in superset/commands/report/alert.py, while scheduled reports capture static snapshots of charts and dashboards.
  • Notification channels are implemented as distinct classes in superset/reports/notifications/: EmailNotification requires SMTP configuration, SlackNotification requires a bot token, and WebhookNotification requires the ALERT_REPORT_WEBHOOK feature flag.
  • Configuration happens in superset_config.py through standard SMTP variables (SMTP_HOST, SMTP_USER), SLACK_API_TOKEN, and feature flags like ALERT_REPORT_WEBHOOK and SLACK_V2_API.
  • Execution relies on Celery Beat reading ReportSchedule.crontab and dispatching tasks via superset/commands/report/execute.py, which instantiates the appropriate notification classes based on ReportRecipientType.
  • Programmatic access is available through the Superset ORM by creating ReportSchedule and ReportRecipient objects directly in superset/reports/models.py.

Frequently Asked Questions

How do I enable webhook notifications in Apache Superset?

Enable the ALERT_REPORT_WEBHOOK feature flag in superset_config.py by setting FEATURE_FLAGS = {"ALERT_REPORT_WEBHOOK": True}. Additionally, set ALERT_REPORTS_WEBHOOK_HTTPS_ONLY = True to restrict webhooks to HTTPS endpoints only. Once enabled, you can add webhook recipients in the Alerts & Reports UI by selecting "Webhook" and providing the target URL.

What SMTP settings are required for email alerts?

Configure the following variables in superset_config.py: SMTP_HOST, SMTP_PORT (typically 587 for TLS), SMTP_USER, SMTP_PASSWORD, and MAIL_DEFAULT_SENDER. Optionally customize EMAIL_REPORTS_SUBJECT_PREFIX to tag outgoing messages. These settings are consumed by EmailNotification in superset/reports/notifications/email.py when constructing messages via the send_email_smtp utility.

How does Superset determine if an alert should trigger?

The AlertCommand class in superset/commands/report/alert.py evaluates the alert SQL query and applies the configured validator. For NOT_NULL validators, it checks if the result is non-zero and not NaN. For OPERATOR validators, it compares the query result against a threshold using Python comparison functions. The run() method returns a tuple (triggered, message) indicating whether the notification should proceed.

Can I create alerts and reports programmatically instead of using the UI?

Yes, you can instantiate ReportSchedule and ReportRecipient objects directly from superset/reports/models.py. Create a schedule with type="Alert" or type="Report", set the crontab string, SQL query (for alerts), and validator configuration. Then append ReportRecipient instances with type=ReportRecipientType.EMAIL, SLACK, or WEBHOOK and the appropriate JSON configuration in recipient_config_json. Commit these to the database using the Superset application context.

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 →