Werkstattbericht Content-Automatisierung – Teil 4 von 8. Wie ich für einen meiner Blogs die Beitragsproduktion mit n8n und Claude automatisiert habe: was funktioniert hat, was nicht, und was am Ende dabei herauskam. Zu den anderen Teilen: 1 · 2 · 3 · 4 · 5 · 6 · 7 · 8.
Manchmal steht der Beweis für einen Fehler schon monatelang in deiner Datenbank, und du siehst ihn nur nicht, weil du an der falschen Stelle suchst.
Ich hatte den großen Artikel-Workflow zwei Tage lang Node für Node durchgesehen. Den kleinen Trigger-Workflow daneben – sieben Kästchen, ein Zeitplan, eine Schleife – hatte ich für erledigt gehalten. Was soll da schon sein?
Dann habe ich in die Zeitstempel meiner WordPress-Entwürfe geschaut:
2025-10-14 00:35:19 Urban Survival
2025-10-14 00:35:19 Survival Mythen
2025-10-14 00:35:20 Bushcraft für Kinder
2025-10-14 00:35:20 Outdoor-Küche
Vier Beiträge in zwei Sekunden.
Dies ist Teil 4 des Werkstattberichts. Es geht um Nebenläufigkeit, um Warteschlangen ohne Gedächtnis, und um die unangenehmste Sorte Fehler überhaupt: die, bei der nichts kaputtgeht, sondern einfach dreimal dasselbe passiert.
Der Fund in den Zeitstempeln
Vier Beiträge in zwei Sekunden
Der Trigger-Workflow ist wirklich klein. Sein ganzer Ablauf:
- Zeitplan, alle 20 Minuten
- aus der Google-Tabelle alle Zeilen mit
Status = To Dolesen Loop Over Topics– für jede Zeile:- den Artikel-Workflow ausführen, mit
waitForSubWorkflow: true - 10 Minuten warten
- nächste Zeile
Punkt 4 und 5 sind entscheidend. waitForSubWorkflow: true heißt: Der Trigger wartet, bis der Artikel fertig ist, bevor er weitermacht. Ein Artikel dauert mit Recherche, sieben Modellaufrufen und vier Bildern seine Zeit – sagen wir zwanzig Minuten. Dazu zehn Minuten Pause. Ein Beitrag alle halbe Stunde, sauber nacheinander.
Bei sequentieller Abarbeitung können also niemals vier Beiträge innerhalb von zwei Sekunden entstehen. Rechnerisch ausgeschlossen.
Es sei denn, es liefen mehrere Ausführungen gleichzeitig.
Warum das rechnerisch unmöglich ist – und trotzdem passiert
Der Mechanismus ist, wenn man ihn einmal gesehen hat, offensichtlich:
Der Artikel-Workflow setzt Status = In Progress erst, wenn er startet. Der Trigger liest aber schon vorher alle „To Do“-Zeilen in einem Rutsch in seine Schleife und arbeitet sie danach über Stunden ab.
Zwanzig Minuten später feuert der Zeitplan erneut. Er liest dieselbe Tabelle. Und findet dort alle Zeilen, die die erste Ausführung noch nicht erreicht hat – sie stehen ja noch auf „To Do“.
Jetzt laufen zwei Ausführungen. Zwanzig Minuten später drei. Dann vier.
Ein Schutz dagegen fehlte vollständig: keine Nebenläufigkeitssperre, kein Vormerken der Zeilen, kein Zwischenstatus Queued.
In meinem Fall waren es vier verschiedene Themen – also kein Schaden außer Last. Aber der Mechanismus ist völlig blind dafür, ob es dasselbe Thema ist. Bei 72 wartenden Zeilen kann er denselben Beitrag mehrfach starten. Ob das schon passiert ist, kann ich aus dem Export nicht sehen; er enthält nur die Entwürfe, die ich behalten habe.

Der Mechanismus: ein Zeitplan ohne Gedächtnis
Wer merkt sich, was schon in Arbeit ist?
Das Muster ist so alt wie Warteschlangen, und es hat einen Namen: Race Condition. Zwei Prozesse lesen denselben Zustand, bevor einer von ihnen ihn ändert – und beide handeln daraufhin so, als wären sie allein.
Das klassische Lehrbuchbeispiel ist das Bankkonto, von dem zwei Automaten gleichzeitig abheben. Hier ist es eine Tabelle, aus der zwei Läufe gleichzeitig Arbeit ziehen.
Die saubere Lösung wäre, dass der Lesevorgang und das Vormerken eine untrennbare Einheit bilden: Zeile lesen und im selben Atemzug auf In Progress setzen. Das leistet eine Google-Tabelle nicht ohne Weiteres. Deshalb gibt es zwei praktikable Wege, und ich habe beide genommen.
Exkurs: Concurrency – die Einstellung, die alles löst
n8n hat für genau diesen Fall eine Einstellung, die man leicht übersieht. In den Workflow-Einstellungen steht ein Feld „Concurrency“. Setzt du es auf 1, startet n8n keinen zweiten Lauf dieses Workflows, solange der erste noch läuft.
Ein Feld. Ein Wert. Problem gelöst.
Das ist die Art von Korrektur, die einen etwas ratlos zurücklässt – zwei Tage Fehlersuche, und die Antwort ist ein Eingabefeld, das die ganze Zeit da war.
Ich habe trotzdem noch etwas zweites gemacht, weil es den Aufbau insgesamt gesünder macht: Der Node, der die Tabelle liest, bekommt ein Limit von 1. Jeder Lauf holt sich also genau ein Thema. Damit wird der 20-Minuten-Takt zur eigentlichen Produktionsrate, statt nur ein Startsignal für eine unbegrenzte Warteschlange zu sein.
Und dann habe ich den Takt selbst angefasst. Alle 20 Minuten ergibt rechnerisch 72 Beiträge pro Tag. Ich will vierzehn pro Woche. Das sind zwei am Tag.
Ein Wort dazu, warum ich nicht einfach 72 nehme, wenn es doch geht: Ich kann dir nicht belegen, ab welcher Frequenz Google eine Domain als auffällig einstuft – dazu gibt es keine offizielle Aussage, und wer dir eine Zahl nennt, hat sie sich ausgedacht. Was ich sagen kann: Eine Seite, die vier Jahre lang unregelmäßig publiziert hat und plötzlich 72 Beiträge am Tag ausstößt, verändert ihr Muster sprunghaft. Und ich habe schlicht keinen Bedarf – 1.121 geplante Beiträge sind bei vierzehn pro Woche achtzig Wochen Arbeit. Das reicht.
Die Kehrseite: Läufe, die nie enden und nie auffallen
Status „In Progress“, für immer
Der Artikel-Workflow setzt am Anfang Status = In Progress und am Ende Status = Done. Dazwischen liegen rund zwanzig Nodes, die scheitern können – ein Modellaufruf ohne Antwort, ein Bild-Upload über dem Größenlimit, eine Google-Tabelle, auf die kein Zugriff besteht.
Es gibt keinen Fehlerpfad, der den Status zurücksetzt. In den Workflow-Einstellungen war auch kein Error-Workflow hinterlegt.
Die Folge ist tückisch: Eine abgebrochene Zeile bleibt auf „In Progress“ stehen. Sie wird vom Trigger nicht erneut aufgegriffen – gut. Sie taucht aber auch nirgends als Fehler auf – schlecht. Bei vierzehn Beiträgen pro Woche merkst du das erst, wenn du die Tabelle einmal von Hand durchsiehst und dich wunderst, warum nur elf angekommen sind.
Dasselbe Muster an einer zweiten Stelle: Der Node Check Inputs prüft die Pflichtspalten – und sein Falsch-Zweig war nicht verbunden. Fehlt eine Pflichtangabe, endet der Lauf stumm. Kein Beitrag, keine Meldung, nichts.
Das habe ich bewusst nicht im Vorbeigehen repariert, sondern als Umbau markiert. Zwei Wege stehen zur Wahl: entweder in den Workflow-Einstellungen einen Error-Workflow eintragen, der Status = Fehler zurückschreibt; oder an die kritischen Nodes einen Fehlerausgang legen, der auf einen zusätzlichen Tabellen-Node „Status = Fehler“ führt. Beides ist mehr als ein Feld, und ein Blindeingriff in eine Fehlerbehandlung, die man nicht durchgetestet hat, macht die Lage selten besser.
Die Endlosschleife mit Rechnung
Ein Befund, der mir beim Lesen einen kleinen Schreck eingejagt hat.
Es gibt einen Node namens Check empty output. Liefert der Blog Planner nichts, geht der Falsch-Zweig zurück zum Blog Planner. Erneuter Versuch. Vernünftige Idee.
Nur ohne Zähler.
Liefert der Planner dauerhaft leeren Output – wegen eines API-Fehlers, eines Formatproblems, einer Inhaltssperre –, dreht diese Schleife unbegrenzt weiter. Und jede Runde ist ein bezahlter Modellaufruf.
Ich habe es nicht im Workflow gelöst, und zwar aus einem Grund, den ich für lehrreich halte: Der naheliegende Einzeiler ist falsch. In der bestehenden UND-Bedingung ein $runIndex < 3 zu ergänzen, erzeugt genau den umgekehrten Fehler – die Schleife bricht dann ab, wenn sie nicht mehr gebraucht wird, und läuft weiter, wenn sie es wird. Eine saubere Begrenzung braucht eine zusätzliche Verzweigung.
Stattdessen habe ich in den Workflow-Einstellungen eine Execution Timeout gesetzt. Das begrenzt den Schaden zuverlässig, kostet einen Klick, und ist unabhängig davon richtig.
Merksatz für Automatisierungen mit bezahlten Aufrufen: Jede Schleife, die auf einen Erfolg wartet, braucht eine Obergrenze. Nicht weil sie oft ausgelöst wird, sondern weil sie im Fehlerfall genau das tut, wovor du dich fürchtest – nur schneller.

Nebenbefunde aus fremder Werkstatt
Das Formular, das in die Tabelle des Vorlagenautors schreibt
Der Trigger-Workflow hat neben dem Zeitplan noch einen zweiten Eingang: ein Web-Formular, über das man ein neues Thema anlegen kann. Der Node dahinter schreibt in ein Google-Dokument mit der ID
12WRp6-aYoQV5r_n1TFnb75HPrwKs_zEMT7tqijC3yzk
Name: „2nd Level Deeper Research – Create Topics“.
Meine eigene Tabelle ist eine andere (1nbRtkDKvN29LzY7y8…, „AI_automation_wildnisruf“). Das da oben ist die Tabelle des Vorlagenautors.
Über das Formular angelegte Themen wären also entweder in einem fremden Dokument gelandet oder – wahrscheinlicher – der Node wäre am fehlenden Zugriff gescheitert. Und weil es keinen Fehlerpfad gibt, siehe oben: stumm.
Dasselbe fremde Dokument tauchte auch in zwei Nodes des großen Workflows als Rückstand auf. Bei einem war zusätzlich eine nackte Blatt-ID 1262763908 eingetragen. Ob es in meinem Dokument ein Blatt mit dieser ID gibt, habe ich nicht geprüft – falls nicht, scheitert der Node.
Wenn du eine Vorlage übernimmst, ist das der Punkt, den ich zuerst prüfen würde: Jeder Node, der auf ein externes Dokument zeigt – Google Sheets, Google Docs, Drive-Ordner – kann auf das Original des Autors zeigen. Es sieht im Node völlig normal aus. Der Unterschied fällt erst auf, wenn man die IDs vergleicht.
Da ich meine Themen ohnehin aus vorbereiteten Tabellen einspiele, habe ich den Formular-Zweig schlicht deaktiviert.
Nachtrag: Sekunden, nicht Stunden
Zum Schluss die Auflösung einer Frage aus Teil 2. Dort hatte ich sieben Wait-Nodes gefunden, die auf amount: 3 standen, ohne gesetzte Einheit. Drei Sekunden? Drei Stunden? Ich hatte es als offen markiert, weil ich es nicht sicher wusste.
Zwei Beobachtungen haben es geklärt:
Erstens: Der Trigger-Workflow setzt seinen eigenen Wait-Node ausdrücklich auf minutes. Die Einheit wird also durchaus gesetzt, wenn sie gemeint ist – ein Indiz dafür, dass der unbeschriftete Fall die Voreinstellung meint.
Zweitens, und das ist der eigentliche Beweis: Zwischen dem ersten Entwurf des Abends (13.10., 23:23) und der Vierergruppe (14.10., 00:35) liegen 72 Minuten. Bei sieben Wartezeiten à drei Stunden wäre kein einziger Beitrag fertig geworden.
Damit ist die Frage erledigt: Es sind Sekunden.
Ich erzähle das nicht, weil das Ergebnis spannend wäre, sondern wegen des Wegs dorthin. Ich hätte in der Dokumentation nachschlagen können und wäre bei einer Aussage gelandet, die für meine n8n-Version stimmen mag oder nicht. Stattdessen habe ich in Daten geschaut, die aus meiner Installation stammen. Zeitstempel lügen nicht.
Fazit
Der Trigger-Workflow hat sieben Nodes. Er enthielt drei Befunde, von denen einer – die parallelen Läufe – unbemerkt zusätzliche Last erzeugt hat, und der zweite dafür sorgt, dass gescheiterte Läufe unsichtbar bleiben.
Die Korrekturen, in dieser Reihenfolge:
- Concurrency auf 1 in den Workflow-Einstellungen – das allein löst die parallelen Läufe
Limitauf 1 Zeile beim Lesen der Tabelle – ein Lauf, ein Thema- Takt entspannen – 20 Minuten ergibt 72 Beiträge am Tag, ich brauche zwei
- Formular-Zweig deaktivieren – er schreibt in eine fremde Tabelle
- Execution Timeout setzen – Deckel auf die Endlosschleife
Und die Erkenntnis, die ich mitnehme: Der kleine Workflow ist nicht der harmlose. Ich habe zwei Tage in 120 Nodes gesucht und den Fehler, der die Produktion tatsächlich außer Takt gebracht hat, in sieben gefunden. Die Größe eines Bauteils sagt nichts über sein Risiko – ein Zeitplan, der Arbeit verteilt, ist strukturell gefährlicher als ein Copywriter, der einen Absatz schreibt.
Im nächsten Teil wird es konstruktiver. Da reiße ich die interne Verlinkung komplett heraus und baue sie neu – und der Anlass dafür ist ein Ankertext, der „Jagdem pflicht um“ lautete.
Alle Teile der Serie
- Teil 1: Null Klicks in drei Monaten
- Teil 2: 120 Nodes geerbt
- Teil 3: Schlachttiere im Wildbret-Beitrag
- Teil 4: Vier Beiträge in zwei Sekunden (dieser Beitrag)
- Teil 5: Interne Verlinkung, neu gebaut
- Teil 6: Yoast über die REST-API
- Teil 7: Stil, Modelle und Kosten
- Teil 8: Bilanz nach zwei Tagen
◀ Zurück zu Teil 3: Schlachttiere im Wildbret-Beitrag | Weiter zu Teil 5: Interne Verlinkung, neu gebaut ▶

Schreibe einen Kommentar