OCNORA
opsbeginner5 min setupby Mantle

Scheduled health check with email alert

Ping an endpoint every 5 minutes; if it does not return 200, email the on-call address with the status code.

Drag to pan, pinch to zoom. This is the real graph the template installs.

How it works

What it does

  • Every 5 minutes, GET the health URL (one retry after 2 s).
  • Healthy? routes a non-200 status to Alert on-call; a 200 ends quietly.
  • The dashed error edge from the request also alerts when the request itself fails (timeout, DNS).

Setup

  • Change the url on GET /health and the interval_sec on the trigger.
  • Set the recipient and a SendGrid / SMTP connection on Alert on-call.

Nodes 5

  1. 01Every 5 minutestrigger.scheduleTrigger
  2. 02GET /healthhttp.requestHTTP
  3. 03Healthy?control.branchLogic
  4. 04Alert on-callmail.sendDestination
  5. 05Healthy — stopcontrol.filterLogic
View template JSON
{
  "format": "mantle-workflow/v1",
  "id": "ops-http-health-check",
  "name": "Scheduled health check with email alert",
  "graph": {
    "nodes": [
      {
        "id": "schedule",
        "type": "trigger.schedule",
        "label": "Every 5 minutes",
        "config": {
          "interval_sec": 300,
          "timezone": "UTC"
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 60,
          "y": 220
        }
      },
      {
        "id": "ping",
        "type": "http.request",
        "label": "GET /health",
        "config": {
          "method": "GET",
          "url": "https://example.com/health",
          "timeout_seconds": 10
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 380,
          "y": 220
        },
        "retry": {
          "max_attempts": 2,
          "backoff": "fixed",
          "initial_ms": 2000,
          "max_ms": 2000
        }
      },
      {
        "id": "branch_healthy",
        "type": "control.branch",
        "label": "Healthy?",
        "config": {
          "mode": "first_match"
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 700,
          "y": 220
        }
      },
      {
        "id": "send_alert",
        "type": "mail.send",
        "label": "Alert on-call",
        "config": {
          "to": "oncall@example.com",
          "subject": "[ALERT] health check failed ({{ steps.ping.status_code }})",
          "body_text": "GET https://example.com/health returned {{ steps.ping.status_code }} at {{ $now }}.\n\nBody:\n{{ steps.ping.body }}"
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 1020,
          "y": 410
        }
      },
      {
        "id": "all_good",
        "type": "control.filter",
        "label": "Healthy — stop",
        "config": {
          "expr": "status_code == 200"
        },
        "connection_id": null,
        "worker_type": "generic-worker",
        "position": {
          "x": 1020,
          "y": 30
        }
      }
    ],
    "edges": [
      {
        "from": "schedule",
        "to": "ping"
      },
      {
        "from": "ping",
        "to": "branch_healthy"
      },
      {
        "from": "branch_healthy",
        "to": "send_alert",
        "branch": "true",
        "condition": {
          "match": "all",
          "rules": [
            {
              "left": "status_code",
              "op": "not_equals",
              "right": 200
            }
          ]
        },
        "label": "not 200"
      },
      {
        "from": "branch_healthy",
        "to": "all_good",
        "branch": "false",
        "label": "200 OK",
        "priority": 1
      },
      {
        "from": "ping",
        "to": "send_alert",
        "branch": "error",
        "label": "request failed"
      }
    ]
  }
}

Use it, then make it yours.

Templates install as drafts. Change anything, and Workflow Health re-checks the graph on every save.