The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "Health & Drift Report (Server-only, StaticData)",
"nodes": [
{
"parameters": {
"triggerTimes": {
"item": [
{
"mode": "everyDay",
"hour": 2,
"minute": 30
}
]
}
},
"type": "n8n-nodes-base.cron",
"typeVersion": 2,
"position": [
-600,
-120
],
"id": "Cron"
},
{
"parameters": {
"url": "={{$json.baseUrl || $env.N8N_BASE_URL || \"http://localhost:5678\"}}/rest/workflows",
"options": {
"headers": {
"entries": [
{
"name": "Authorization",
"value": "={{\"Bearer \" + ($json.apiKey || $env.N8N_API_KEY || $json.N8N_API_KEY)}}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
-260,
-200
],
"id": "GetWorkflows",
"name": "GET /rest/workflows"
},
{
"parameters": {
"url": "={{$json.baseUrl || $env.N8N_BASE_URL || \"http://localhost:5678\"}}/rest/executions-current",
"options": {
"headers": {
"entries": [
{
"name": "Authorization",
"value": "={{\"Bearer \" + ($json.apiKey || $env.N8N_API_KEY || $json.N8N_API_KEY)}}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
-260,
0
],
"id": "GetExecRunning",
"name": "GET /rest/executions-current"
},
{
"parameters": {
"url": "={{$json.baseUrl || $env.N8N_BASE_URL || \"http://localhost:5678\"}}/rest/executions?limit=25",
"options": {
"headers": {
"entries": [
{
"name": "Authorization",
"value": "={{\"Bearer \" + ($json.apiKey || $env.N8N_API_KEY || $json.N8N_API_KEY)}}"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
-260,
200
],
"id": "GetExecRecent",
"name": "GET /rest/executions?limit=25"
},
{
"parameters": {
"functionCode": "const prev = this.getWorkflowStaticData('global');\n\n// Normalize helper\nfunction indexById(arr) {\n const idx = {};\n for (const w of arr) idx[w.id] = {\n id: w.id,\n name: w.name,\n active: !!w.active,\n updatedAt: w.updatedAt || w.updatedAtUNIX || null,\n versionId: w.versionId || null\n };\n return idx;\n}\n\n// Read inputs\nconst wfRaw = items[0].json; // from GET /rest/workflows\nconst list = (wfRaw.data || wfRaw || []);\nconst runningRaw = items[1].json; // executions-current\nconst recentRaw = items[2].json; // executions?limit=25\n\nconst now = new Date().toISOString();\nconst current = list.map(w => ({\n id: w.id,\n name: w.name,\n active: !!w.active,\n updatedAt: w.updatedAt || w.updatedAtUNIX || null,\n versionId: w.versionId || null\n}));\n\nconst prevList = prev.snapshot || [];\nconst idxPrev = indexById(prevList);\nconst idxCurr = indexById(current);\n\n// Diff\nconst added = [];\nconst removed = [];\nconst updated = [];\n\nfor (const id of Object.keys(idxCurr)) {\n if (!idxPrev[id]) {\n added.push(idxCurr[id]);\n } else {\n const a = idxPrev[id];\n const b = idxCurr[id];\n if (a.updatedAt !== b.updatedAt || a.active !== b.active || a.versionId !== b.versionId || a.name !== b.name) {\n updated.push({ before: a, after: b });\n }\n }\n}\nfor (const id of Object.keys(idxPrev)) {\n if (!idxCurr[id]) removed.push(idxPrev[id]);\n}\n\nconst report = {\n generatedAt: now,\n baseUrl: $json.baseUrl || $env.N8N_BASE_URL || 'http://localhost:5678',\n summary: {\n total: current.length,\n running: (runningRaw.data || runningRaw || []).length || 0,\n recent: (recentRaw.data || recentRaw || []).length || 0,\n added: added.length,\n removed: removed.length,\n updated: updated.length\n },\n drift: { added, removed, updated },\n note: 'Persistenz via Workflow Static Data; erster Lauf markiert alles als added.'\n};\n\n// Persist current as new snapshot\nprev.snapshot = current;\nprev.lastRun = now;\n\nreturn [{ json: report }];"
},
"type": "n8n-nodes-base.function",
"typeVersion": 2,
"position": [
60,
0
],
"id": "BuildReport",
"name": "Build Report & Persist"
},
{
"parameters": {
"url": "={{$env.SLACK_WEBHOOK_URL || $json.SLACK_WEBHOOK_URL}}",
"options": {
"headers": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"body": "={\n \"text\": \"n8n Health & Drift\\n\" +\n \"total:\" + $json.summary.total + \", running:\" + $json.summary.running + \", recent:\" + $json.summary.recent + \"\\n\" +\n \"added:\" + $json.summary.added + \", removed:\" + $json.summary.removed + \", updated:\" + $json.summary.updated\n}",
"sendBinaryData": false
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
360,
-100
],
"id": "SlackNotify",
"name": "Notify Slack",
"disabled": true
},
{
"parameters": {
"url": "={{\"https://api.telegram.org/bot\" + ($env.TG_BOT_TOKEN || $json.TG_BOT_TOKEN) + \"/sendMessage\"}}",
"queryParametersUi": {
"parameter": [
{
"name": "chat_id",
"value": "={{$env.TG_CHAT_ID || $json.TG_CHAT_ID}}"
},
{
"name": "text",
"value": "={{\"n8n Health & Drift%0A\" + encodeURI(\"total:\" + $json.summary.total + \", running:\" + $json.summary.running + \", recent:\" + $json.summary.recent + \" | added:\" + $json.summary.added + \", removed:\" + $json.summary.removed + \", updated:\" + $json.summary.updated))}}"
}
]
}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4,
"position": [
360,
100
],
"id": "TelegramNotify",
"name": "Notify Telegram",
"disabled": true
},
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-600,
80
],
"id": "Manual"
}
],
"connections": {
"Cron": {
"main": [
[
{
"node": "GET /rest/workflows",
"type": "main",
"index": 0
}
]
]
},
"Manual": {
"main": [
[
{
"node": "GET /rest/workflows",
"type": "main",
"index": 0
}
]
]
},
"GET /rest/workflows": {
"main": [
[
{
"node": "GET /rest/executions-current",
"type": "main",
"index": 0
}
]
]
},
"GET /rest/executions-current": {
"main": [
[
{
"node": "GET /rest/executions?limit=25",
"type": "main",
"index": 0
}
]
]
},
"GET /rest/executions?limit=25": {
"main": [
[
{
"node": "Build Report & Persist",
"type": "main",
"index": 0
}
]
]
},
"Build Report & Persist": {
"main": [
[
{
"node": "Notify Slack",
"type": "main",
"index": 0
}
],
[
{
"node": "Notify Telegram",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"saveExecutionProgress": false,
"timezone": "Europe/Zurich"
},
"staticData": {},
"meta": {
"templateCredsSetup": "Create HTTP Request credential with Bearer token for n8n API if preferred; or use env N8N_API_KEY"
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Health & Drift Report (Server-only, StaticData). Uses httpRequest. Scheduled trigger; 8 nodes.
Source: https://github.com/JowaFlux/n8nselfhosting/blob/212e1c6ce9509f87c8153f75372d7955a7a32e30/n8n/health_drift_report.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Birthday Automation - Production (Fixed). Uses stopAndError, httpRequest, emailSend, bannerbear. Scheduled trigger; 86 nodes.
This template runs two scheduled workflows to govern Microsoft Entra ID (Azure AD) guest accounts by detecting stale users via Microsoft Graph, staging deletions in SharePoint with a 72-hour window, n
Jira-Allure-Auto-Qa. Uses httpRequest, jira. Scheduled trigger; 68 nodes.
Spotify-Sync-Surrealdb-V1. Uses httpRequest, n8n-nodes-surrealdb, spotify. Scheduled trigger; 62 nodes.
As n8n instances scale, teams often lose track of sub-workflows—who uses them, where they are referenced, and whether they can be safely updated. This leads to inefficiencies like unnecessary copies o