utilitiesintermediate10 min setupby Mantle
Delay, retry and dead-letter
Call a flaky endpoint with backoff retries; on final failure wait, try a fallback endpoint, and if that also fails email an operator.
Drag to pan, pinch to zoom. This is the real graph the template installs.
How it works
What it does
- Primary endpoint retries 4× with exponential backoff (1 s → 20 s cap).
- Only if it still fails does the dashed error edge fire: Wait 60s → Fallback endpoint (2 fixed retries).
- If the fallback fails too, Dead-letter to operator emails the payload.
Setup
- Set both
urls and the operator address (SendGrid/SMTP connection). Success paths end silently — add downstream nodes to either call as needed.
Nodes 5
- 01Job intrigger.webhookTrigger
- 02Primary endpointhttp.requestHTTP
- 03Wait 60scontrol.delayLogic
- 04Fallback endpointhttp.requestHTTP
- 05Dead-letter to operatormail.sendDestination
View template JSON
{
"format": "mantle-workflow/v1",
"id": "util-delay-retry-webhook",
"name": "Delay, retry and dead-letter",
"graph": {
"nodes": [
{
"id": "webhook",
"type": "trigger.webhook",
"label": "Job in",
"config": {
"slug": "flaky-job",
"idempotency_path": "job_id"
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 60,
"y": 220
}
},
{
"id": "primary_call",
"type": "http.request",
"label": "Primary endpoint",
"config": {
"method": "POST",
"url": "https://primary.example.com/jobs",
"body_from_input": true,
"timeout_seconds": 10
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 380,
"y": 220
},
"retry": {
"max_attempts": 4,
"backoff": "exp",
"initial_ms": 1000,
"max_ms": 20000
}
},
{
"id": "cool_down",
"type": "control.delay",
"label": "Wait 60s",
"config": {
"seconds": 60
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 700,
"y": 410
}
},
{
"id": "fallback_call",
"type": "http.request",
"label": "Fallback endpoint",
"config": {
"method": "POST",
"url": "https://fallback.example.com/jobs",
"body_from_input": true,
"timeout_seconds": 10
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 1020,
"y": 410
},
"retry": {
"max_attempts": 2,
"backoff": "fixed",
"initial_ms": 5000,
"max_ms": 5000
}
},
{
"id": "dead_letter",
"type": "mail.send",
"label": "Dead-letter to operator",
"config": {
"to": "ops@example.com",
"subject": "Job {{ steps.webhook.job_id }} failed on primary and fallback",
"body_text": "Payload:\n{{ steps.webhook }}"
},
"connection_id": null,
"worker_type": "generic-worker",
"position": {
"x": 1340,
"y": 600
}
}
],
"edges": [
{
"from": "webhook",
"to": "primary_call"
},
{
"from": "primary_call",
"to": "cool_down",
"branch": "error",
"label": "primary failed"
},
{
"from": "cool_down",
"to": "fallback_call"
},
{
"from": "fallback_call",
"to": "dead_letter",
"branch": "error",
"label": "fallback failed"
}
]
}
}Use it, then make it yours.
Templates install as drafts. Change anything, and Workflow Health re-checks the graph on every save.