Skip to content

SQL Alerts in Asset Bundles

Skill: databricks-bundles

SQL alerts let you monitor query results and get notified when a condition is met — row counts dropping below a threshold, error rates spiking, SLA metrics drifting. Defining alerts as DABs resources means they deploy alongside your jobs and pipelines, with environment-specific thresholds and notification targets. The schema has several non-obvious fields that trip people up, so this page covers the correct structure.

“Add a SQL alert to my DABs project that fires when the daily order count drops below 100, checking every morning at 9 AM Pacific.”

resources:
alerts:
low_order_count:
display_name: "[${bundle.target}] Low Order Count"
query_text: "SELECT count(*) AS c FROM analytics.gold.daily_orders WHERE order_date = current_date"
warehouse_id: ${var.warehouse_id}
evaluation:
comparison_operator: 'LESS_THAN'
source:
name: 'c'
display: 'c'
threshold:
value:
double_value: 100
notification:
notify_on_ok: false
subscriptions:
- user_email: "${workspace.current_user.userName}"
schedule:
pause_status: 'UNPAUSED'
quartz_cron_schedule: '0 0 9 * * ?'
timezone_id: 'America/Los_Angeles'
permissions:
- level: CAN_RUN
group_name: "users"

Key decisions:

  • The top-level key is evaluation, not condition. This is the most common mistake — the older API used condition but the bundle schema uses evaluation.
  • The source field sits directly under evaluation, not nested under operand.column. The name must match a column alias from your query_text.
  • Notification subscriptions go inside evaluation.notification, not at the top level. This nesting is unintuitive but required by the schema.
  • All three schedule fields — pause_status, quartz_cron_schedule, and timezone_id — are required. Omitting any one causes a validation error.

“Show me the alert schema so I know which fields are valid.”

Terminal window
databricks bundle schema | grep -A 100 'sql.AlertV2'

Run this before writing alert YAML from memory. The schema changes across CLI versions, and the field names do not match the REST API documentation exactly. This is the ground truth.

“I want to alert when the error count exceeds 50. Which operator do I use?”

# Alert fires when the CONDITION IS TRUE
# "GREATER_THAN" fires when the value IS greater than the threshold
# To alert when errors exceed 50:
evaluation:
comparison_operator: 'GREATER_THAN'
source:
name: 'error_count'
display: 'error_count'
threshold:
value:
double_value: 50

The operator reads as: “fire the alert when source IS comparison_operator threshold.” Available operators: EQUAL, NOT_EQUAL, GREATER_THAN, GREATER_THAN_OR_EQUAL, LESS_THAN, LESS_THAN_OR_EQUAL.

“Set a lower threshold in dev so I can test the alert without waiting for real failures.”

variables:
alert_threshold:
default: 100
targets:
dev:
variables:
alert_threshold: 10
prod:
variables:
alert_threshold: 100
resources:
alerts:
low_order_count:
display_name: "[${bundle.target}] Low Order Count"
query_text: "SELECT count(*) AS c FROM ${var.catalog}.gold.daily_orders"
warehouse_id: ${var.warehouse_id}
evaluation:
comparison_operator: 'LESS_THAN'
source:
name: 'c'
display: 'c'
threshold:
value:
double_value: ${var.alert_threshold}
notification:
notify_on_ok: false
subscriptions:
- user_email: "${workspace.current_user.userName}"
schedule:
pause_status: 'UNPAUSED'
quartz_cron_schedule: '0 0 9 * * ?'
timezone_id: 'America/Los_Angeles'

This pattern deploys the same alert to dev and prod with different thresholds. In dev you set the threshold low enough to trigger during testing. In prod you set it to the real business threshold.

  • Using condition instead of evaluation — the REST API docs and some older examples use condition with operand.column nesting. The bundle schema uses evaluation with source directly underneath. Running databricks bundle validate will catch this, but the error message is not always clear about the fix.
  • Putting subscriptions at the top level — subscriptions must be nested under evaluation.notification.subscriptions, not as a sibling of evaluation. Top-level subscriptions is silently ignored, so your alert fires but nobody gets notified.
  • Forgetting required schedule fieldspause_status, quartz_cron_schedule, and timezone_id are all required. Omitting timezone_id causes a deploy-time error. Omitting pause_status may default to PAUSED, which means your alert never runs.
  • Quartz cron format confusion — the schedule uses six-field Quartz cron (seconds minutes hours day-of-month month day-of-week). Example: '0 0 9 * * ?' runs at 9:00 AM. The ? in day-of-week is required when day-of-month is *.