Schedule icon
TriggerWorkflow icon
Return icon
Switch icon
If icon
SlackIncomingWebhook icon
Log icon

n8n Webhook Canary Health Gate

Trigger an n8n canary workflow via webhook, classify its response status, and alert Slack when n8n stops responding correctly.

Categories
Infrastructure

n8n workflows quietly glue together lead routing, alerting, and integration logic that nobody notices is broken until a customer complains. A webhook misconfiguration, an expired credential inside a workflow node, or n8n itself being down all look identical from the outside unless something actually calls the webhook and checks the response. This blueprint uses plugin-n8n's TriggerWorkflow task to call a dedicated canary workflow on a schedule and classify exactly what kind of failure, if any, comes back.

How it works

  1. trigger_canary_workflow (io.kestra.plugin.n8n.TriggerWorkflow) POSTs a small JSON payload to the canary workflow's webhook and waits for its response. plugin-n8n's own task implementation treats any non-200 HTTP response as a task failure, not a captured output, so allowFailure: true is what lets this flow tell "unreachable or non-200" apart from "reachable with the wrong content" instead of aborting outright.
  2. classify_canary_status (io.kestra.plugin.core.debug.Return) checks whether outputs.trigger_canary_workflow.statusCode is defined at all. If it is missing, the classification is PROBE_FAILED, covering both connectivity failures and non-200 responses. If it is defined and the response body's status field matches expected_status_value, the classification is CANARY_HEALTHY; otherwise CANARY_UNHEALTHY, meaning the webhook answered with HTTP 200 but the workflow itself reported something unexpected.
  3. route_by_canary_status (io.kestra.plugin.core.flow.Switch) branches on that string. CANARY_UNHEALTHY runs evaluate_alert_toggle (io.kestra.plugin.core.flow.If), which pages Slack via dispatch_canary_unhealthy_alert only when send_slack_alert is true, naming the exact mismatch, logging a suppressed-alert line otherwise. CANARY_HEALTHY logs a clean audit line. PROBE_FAILED pages Slack directly since canary health is now unknown. The defaults branch logs a fallback line that is unreachable under normal operation.
  4. log_audit_summary records a status line on every run regardless of branch, so execution history reads as a continuous n8n uptime trend.
  5. The flow-level errors block pages Slack separately if the sentinel flow itself fails outright.
  6. The n8n_canary_schedule trigger polls every 15 minutes with explicit input overrides, shipped disabled: true until pointed at a real canary workflow.

What you get

  • A scheduled, real end-to-end proof that n8n's webhook layer and a known-good workflow are both actually working, not just that the n8n process is running.
  • A three-way status output (CANARY_HEALTHY / CANARY_UNHEALTHY / PROBE_FAILED) other flows can gate on before depending on n8n-driven automations.
  • A Slack page that distinguishes "n8n didn't answer" from "n8n answered but the workflow logic is wrong," which point at different people to page.
  • A separate failure channel for the sentinel flow itself, plus a standing per-run audit log line.

Who it's for

  • Platform and automation engineering teams who run n8n for business-critical glue (lead routing, alerting, integrations) and need to know when it silently breaks.
  • Teams who have been burned by an n8n workflow that "looked active" in the editor but had a dead credential or a broken node.
  • SRE teams standardizing Day 2 synthetic monitoring for workflow automation platforms inside Kestra.

Why orchestrate this with Kestra

A one-off curl against the webhook proves it works for one instant and leaves no record. This flow keeps every canary call in Kestra's execution history, turns the result into a typed status output other flows can depend on, and gives you an If/Switch branch to grow into real remediation (restarting a workflow, opening a ticket) without rewriting the probe itself.

Prerequisites

  • A running n8n instance reachable from the Kestra Worker, with a dedicated canary workflow whose webhook node responds with JSON shaped like {"status": "ok"} (or whatever value matches expected_status_value).
  • The canary workflow's Production webhook URL (not the Test URL, which only fires once per manual trigger in the n8n editor).
  • A Slack incoming webhook for the unhealthy, probe-failure, and flow-failure alerts.

Quick start

  1. In n8n, build a minimal workflow: Webhook node (POST) to Respond to Webhook node returning {"status": "ok"}, then activate it.
  2. Add the N8N_CANARY_WEBHOOK_URL secret with that workflow's Production webhook URL, and the SLACK_WEBHOOK secret.
  3. Run the flow once and confirm status reads CANARY_HEALTHY.
  4. Enable n8n_canary_schedule.

How to extend

  • Have the canary workflow's final node include a timestamp or version field in its JSON response, and extend the classification to also flag a response that is unexpectedly stale.
  • Fan this out across several canary workflows (one per critical automation) with a Loop task, reusing the same trigger-and-classify shape per webhook.
  • Push status into a KV store to alert only on state transitions instead of every run.
  • On CANARY_UNHEALTHY, chain a follow-up n8n webhook call that attempts a safe workflow re-activation, gated behind a dry-run toggle.

Secrets

  • N8N_CANARY_WEBHOOK_URL: production webhook URL of the dedicated canary n8n workflow; plugin-n8n marks this property as secret-worthy since the URL itself often doubles as the webhook's access control.
  • SLACK_WEBHOOK: Slack incoming webhook used for the unhealthy, probe-failure, and flow-failure alerts.
  • OSS note: if your Kestra instance reads secrets from environment variables instead of a secrets backend, set SECRET_N8N_CANARY_WEBHOOK_URL and SECRET_SLACK_WEBHOOK as base64, for example echo -n "<your-value>" | base64.

Inputs

  • expected_status_value (STRING, default "ok"): value expected under the canary workflow's JSON status field.
  • send_slack_alert (BOOLEAN, default true): when true, page Slack on an unhealthy result; when "false", only log it.

Outputs

  • {{ outputs.trigger_canary_workflow.statusCode }}: HTTP status code returned by the n8n webhook, populated only on a 200 response.
  • {{ outputs.trigger_canary_workflow.body }}: parsed JSON (or raw text) response body from the canary workflow.
  • {{ outputs.classify_canary_status.value }}: classification string, one of CANARY_HEALTHY, CANARY_UNHEALTHY, PROBE_FAILED.
  • {{ outputs.status }}: flow-level alias of the same classification.

Pitfalls

  • plugin-n8n's TriggerWorkflow task fails outright on any non-200 response rather than returning a captured status code; this blueprint relies on that behavior to fold "unreachable" and "non-200" together into PROBE_FAILED via allowFailure: true, it does not distinguish a 404 from a timeout from a 500.
  • Using the n8n Test URL instead of the Production URL will make this sentinel pass on manual runs but silently stop firing once the editor is closed; always point N8N_CANARY_WEBHOOK_URL at the Production webhook URL.
  • outputs.trigger_canary_workflow.body.status assumes the canary workflow responds with Content-Type: application/json; plugin-n8n only parses JSON when that header is present, otherwise body is a raw string and this comparison will not match.
  • This probe only proves the canary workflow itself works; a different workflow on the same n8n instance can still be broken independently. Fan the probe out across more canary workflows for broader coverage, per How to extend.
  • A 15-minute poll interval can miss a brief outage that recovers between two runs.

Local Container Setup

To start a local n8n instance for testing, execute:

docker volume create n8n_data docker run -d --name kestra-n8n -p 5678:5678 -v n8n_data:/home/node/.n8n docker.n8n.io/n8nio/n8n

Open http://localhost:5678, build the canary workflow described in Quick start, and copy its Production webhook URL into the N8N_CANARY_WEBHOOK_URL secret.

If Kestra is running inside a Docker network, connect the n8n container to Kestra's network:

docker network connect YOUR_KESTRA_NETWORK kestra-n8n

(Run docker network ls to verify your active Kestra network name.)

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.