Die Hybrid-Aufteilung oben ist richtig, daher werde ich nur die Teile hinzufügen, die in der Produktion problematisch sind, sobald du sie gebaut hast, denn zwei davon widersprechen bereits im Thread gegebenen Ratschlägen.
Zunächst wird der zentralisierte Error Trigger-Workflow den Absturz des Workers, den du aufgelistet hast, nicht abfangen. Der Error Trigger wird ausgelöst, wenn eine Ausführung in einem Fehlerzustand endet, was bedeutet, dass die Ausführung lange genug bestehen bleiben muss, um festzuhalten, dass sie fehlgeschlagen ist. Ein Worker, der durch OOM (Out of Memory) abgetötet oder dessen Container vertrieben wird, stirbt, bevor er diesen Endzustand schreiben kann, sodass die Ausführung in einem Running- oder Crashed-Zustand verbleibt und kein Error Trigger jemals ausgelöst wird. Der zentralisierte Workflow ist das richtige Zuhause für Logging und Alerting, aber er sieht nur Fehlschläge, die ordentlich genug sind, um sich selbst zu melden, und ein harter Absturz ist keiner davon.
Das weist auf die größere Lücke hin: die Fehlerklasse, die überhaupt keine Ausführung erzeugt. Dein JSON-Schema und eine State Table können nur Läufe aufzeichnen, die gestartet wurden. Der geplante Trigger, der stillschweigend aufhört zu feuern, der Workflow, den jemand deaktiviert ließ, der Webhook, dessen Registrierung bei einem Neustart verloren ging, die Queue, die nicht mehr verarbeitet wird, weil der einzige Worker gestorben ist: keiner von denen erzeugt eine Ausführung, also keiner erzeugt eine Fehlerzeile, und dein Monitoring zeigt null Fehler. Null Fehler sieht identisch aus wie ein sauberer Tag und wie ein Workflow, der seit sechs Stunden tot ist. Das Einzige, das es abfängt, ist eine Erwartung, die außerhalb von n8n gehalten wird. Jeder erfolgreiche Lauf schreibt einen Heartbeat, einen Last-Success-Timestamp pro Workflow, und eine separate billige Prüfung alarmt, wenn ein Workflow, der in den letzten N Minuten hätte laufen sollen, nicht gelaufen ist. Das ist Absence Detection, und es ist ein anderer Mechanismus als alles andere im Thread, weil es auf das Fehlen einer Zeile reagiert, nicht auf deren Inhalt.
Zweitens, zur Idempotenz, eine Korrektur zum Pattern oben: Verwende nicht die Webhook-Ausführungs-ID als Schlüssel. Ein Recovery-Lauf ist eine neue Ausführung mit einer neuen Ausführungs-ID, daher bedeutet das Keying darauf, dass die Recovery das Original nicht erkennen kann und dein Upsert nicht dedupen kann. Der Schlüssel muss aus der Business-Payload kommen, etwas Stabiles über jeden Retry des gleichen logischen Requests hinweg, und er muss vor dem externen Aufruf geschrieben werden, nicht danach. So bleibt ein Datensatz erhalten, dass die Aktion versucht wurde, selbst wenn zwischen dem API-Aufruf und dem Save Result-Schritt abgestürzt wird. Andernfalls ist der gefährliche Fall derjenige, der sauber aussieht: der External API Call ist erfolgreich, der Worker stirbt vor Save Result, es gibt keine fehlgeschlagene Zeile irgendwo, und Recovery führt fröhlich eine Aktion erneut aus, die bereits passiert ist.
Für das, was es wert ist: Diese Art von Production Hardening, besonders die Monitoring-Schicht und die Absence Detection, ist das, was ich für Leute mache, die n8n in der Produktion betreiben. Falls du also eine Hand brauchst, um es in etwas zu verwandeln, auf das du dich wirklich verlassen kannst, gerne im Gespräch. Auf jeden Fall ist der Heartbeat das Stück, das ich zuerst bauen würde.