Run icon
DiscordIncomingWebhook icon
Schedule icon

Hex Notebook SLA Guard with Timeout Paging

Enforce a runtime SLA on Hex notebooks with Kestra. maxDuration fails runs that overshoot the budget and pages Discord as a breach, with timing on success.

Categories
BusinessData

A notebook that normally takes four minutes and suddenly takes forty is telling you something, a query regressed, a table exploded, an upstream source is limping. Without a budget, that signal arrives as a vague "the dashboard feels slow lately" weeks later. This blueprint gives the run a contract: io.kestra.plugin.hex.projects.Run executes with maxDuration bound to a flow input, so any run that overshoots the SLA fails the task and pages Discord as a breach, while healthy runs report their actual elapsed time against the budget.

How it works

  1. The sla input (type DURATION, default ten minutes) defines the runtime budget, and run_within_sla passes it straight into the Run task's maxDuration.
  2. With wait: true, the task polls the run every ten seconds; if the run has not reached a terminal state when maxDuration elapses, the task fails, and a run that errors in Hex fails it too.
  3. Both failure paths route into the errors block, where page_sla_breach posts an explicit incident-style message to Discord naming the budget that was broken.
  4. On success, report_healthy posts the run's elapsedTime next to the SLA, so the channel watches the margin shrink over weeks instead of discovering the breach cold.
  5. A disabled-by-default hourly business-hours Schedule exercises the guard so regressions surface the hour they appear.

What you get

  • A hard runtime budget on a notebook, enforced by the orchestrator rather than by whoever happens to notice.
  • Breaches that page as incidents, with the flow, execution, and budget named in the message.
  • Elapsed-versus-budget reporting on every healthy run, turning runtime drift into a visible trend.
  • An SLA that is a flow input, so tightening it for a critical dashboard is a parameter change, not an edit.

Who it's for

  • Data platform teams that publish runtime commitments for the dashboards executives read.
  • Analytics engineers who want performance regressions in notebook SQL caught by machinery, not by complaints.
  • Anyone who has learned that a 40-minute notebook run is an incident, not a curiosity.

Why orchestrate this with Kestra

Hex runs the notebook as long as it takes; it has no concept of how long it should take. Kestra imposes the contract from outside: maxDuration turns time into a failure condition, the errors block turns that failure into a page, and the execution history holds every run's timing for the postmortem. The same guard pattern then applies unchanged to any other task in your stack with a runtime promise.

Prerequisites

  • A Hex project and its project ID, plus a realistic sense of its normal runtime.
  • A Hex API token with permission to run the project.
  • A Discord incoming webhook for both the healthy reports and the breach pages.

Secrets

  • HEX_API_TOKEN: Hex API token used to run the project.
  • DISCORD_WEBHOOK_URL: Discord incoming webhook URL.

Quick start

  1. Add the HEX_API_TOKEN and DISCORD_WEBHOOK_URL secrets to your Kestra namespace.
  2. Set project_id, leave the default ten-minute SLA, and execute the flow; Discord should report the elapsed time against the budget.
  3. Execute again with sla set below the notebook's real runtime to see the breach page, then set a budget with sensible headroom and enable the hourly trigger.

How to extend

  • Route breach pages to a dedicated incidents channel while healthy reports stay in the team channel.
  • Guard several notebooks by looping project IDs with ForEach, each against the same or a per-project budget.
  • Chain the guarded run behind your warehouse load so the SLA measures the notebook, not upstream lateness.
  • Feed elapsedTime into a metrics store from a downstream task to alert on trend, not only on breach.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.