n8n von 1.x auf 2.x: Wie wir unsere eigene Instanz umgezogen haben, ohne dass am Morgen etwas fehlte

Wie wir eine selbst gehostete n8n-Instanz mit 33 Workflows von 1.71 auf 2.43 gehoben haben – mit Generalprobe, zwei Sprüngen und Rückweg.

Ein Update von n8n ist normalerweise kein Thema. Neues Image, Container neu starten, fertig.

Der Sprung von 1.x auf 2.x ist anders. Die Datenbank wird migriert, und danach gibt es kein einfaches Zurück mehr – den alten Image-Tag wieder einzutragen reicht nicht, weil die alte Version mit dem neuen Schema nichts anfangen kann. Bei uns hängen an dieser Instanz 33 Workflows, 21 davon aktiv: Kronjobs am frühen Morgen, Webhooks für Veröffentlichungen, Freigaben per Telegram-Button. Wenn da nachts etwas still kaputtgeht, merkt man es erst, wenn morgens die Nachricht fehlt.

Also haben wir es nicht wie ein Update behandelt, sondern wie einen Umzug.

Erst die Generalprobe, dann die echte Instanz

Gestartet sind wir mit Backups, und zwar doppelt: eine Online-Kopie der SQLite-Datenbank über die Backup-API (Integritätsprüfung ok), dazu das komplette Volume – inklusive der config-Datei mit dem Verschlüsselungsschlüssel. Die wird gern vergessen. Ohne sie sind alle Credentials in der Sicherung nur Zeichensalat.

Dann kam die eigentliche Arbeit: eine Kopie der Instanz als Klon auf demselben Server, ohne Netzwerk und mit hartem Speicherlimit von 1 GB. Ohne Netz heißt: Der Klon kann niemandem eine echte Telegram-Nachricht schicken oder einen Beitrag veröffentlichen, auch wenn ein Kronjob losläuft. (Das Limit hat übrigens einmal zugeschlagen – der Klon wurde vom OOM-Killer beendet, die echte Instanz hat davon nichts gemerkt. Genau dafür war es da.)

In der Kopie der Datenbank haben wir jedem der 20 produktiven Workflows einen zusätzlichen Test-Webhook verpasst, verbunden mit derselben Stelle wie der echte Trigger. So ließ sich jeder Workflow gezielt anstoßen. Weil es kein Netz gab, ist natürlich jeder beim ersten externen Aufruf an der DNS-Auflösung gescheitert – aber eben erst dort. Alles davor lief durch, und das war die Aussage, die wir brauchten.

Dazu ein kleiner Probe-Workflow mit einer Code-Node, der prüft, was in der Sandbox noch geht: $env, this.helpers, $getWorkflowStaticData, Buffer, require('crypto'), fetch.

Zwei Sprünge statt einem

Wir sind nicht direkt von 1.71.3 auf 2.43.2 gegangen, sondern über 1.123.84, die letzte 1.x-Version. Jeder Schritt wurde im Klon einzeln gemessen:

1.71.3 1.123.84 2.43.2
Start inkl. Migration 18 s 21 s 24 s
Credentials entschlüsselt 21/21 21/21 21/21
Workflows bis zum ersten externen Aufruf ok ok ok
Speicher n8n 199 MB 467 MB 540 MB

Der Speicher ist die Zahl, die man ernst nehmen sollte. Auf einem kleinen VPS, auf dem noch Analytics, Datenbank und eine Website laufen, sind 300 MB mehr kein Detail.

Was sich in 2.x tatsächlich anders verhält

Ehrlich gesagt weniger, als die Release Notes befürchten lassen. Aber ein paar Dinge haben wir notiert:

require('crypto') in der Code-Node ist in 2.x ausdrücklich gesperrt. Bei uns ging es allerdings schon in 1.71 nicht – die Fehlermeldung ist nur eine andere. Gleiches gilt für fetch, das war schon vorher undefined. Wer externe Aufrufe aus Code-Nodes heraus macht, sollte das ohnehin in eine HTTP-Request-Node verlagern.

Das Timeout der Code-Node. Wir haben N8N_RUNNERS_TASK_TIMEOUT=300 explizit gesetzt, damit unsere längeren Code-Schritte ihre fünf Minuten behalten. Laut Hinweisen soll der Standard künftig bei 60 Sekunden liegen, und wir wollten das nicht beim nächsten Update im Log entdecken.

$env in Nodes braucht weiterhin N8N_BLOCK_ENV_ACCESS_IN_NODE=false, wenn man es nutzt. Bei uns sind es neun Workflows.

Ein Workflow wurde von selbst aktiv. Nach der Migration war unser Error-Workflow (Error Trigger → Telegram) plötzlich als aktiv markiert, statt 21 also 22 aktive Workflows im Klon. Klingt nach Fehler, ist aber gewollt: Die Migration veröffentlicht Workflows mit Error Trigger. Das Verhalten ist dasselbe wie vorher – er springt an, wenn ein anderer Workflow scheitert.

Und dann das eine, das die Generalprobe nicht finden konnte.

Die Überraschung kam eine Woche später

Eine Woche nach dem Update lieferte eine Freigabe per Telegram-Button plötzlich 401 Invalid token. Hintergrund: In 2.x verlangt der Endpunkt /webhook-waiting/<execution-id>, über den eine Wait-Node fortgesetzt wird, eine Signatur als Parameter ?signature=…. Der passende Token steckt in den Daten der Execution (resumeToken) und lässt sich über die öffentliche API abfragen. Unser Listener, der die Button-Klicks entgegennimmt, macht das inzwischen so.

Im Klon ohne Netz und ohne echte Pausen war das nicht zu sehen. Was daraus folgt: Wait-Nodes, die von außen fortgesetzt werden, gehören nach einem 2.x-Update auf die Liste der Dinge, die man in den ersten Tagen gezielt beobachtet – nicht nur in der ersten Stunde.

Der eigentliche Wechsel

Am Ende war der Produktivwechsel der unspektakulärste Teil. Kurz nach Mitternacht: n8n stoppen, das Volume noch einmal im gestoppten Zustand sichern, dazu ein Snapshot des ganzen Servers. Dann Tag 1.123.84, hochfahren, prüfen. Dann Tag 2.43.2, hochfahren, prüfen. Geplant waren rund zwei Minuten Ausfall – zwei Neustarts zu je etwa 25 Sekunden, dazu die Kontrollen.

Geprüft wurde nicht nur, ob /healthz antwortet. Sondern auch: Stimmt die Zahl der aktiven Workflows (21 – die 20 alten plus der Error-Workflow)? Sind die registrierten Webhooks und die wartenden Executions dieselben wie vorher? Antworten die Webhooks genauso wie vor dem Update? Am nächsten Morgen dann der eigentliche Test – alle nächtlichen Kronjobs liefen erfolgreich.

Der Rückweg war vorher aufgeschrieben: altes Image plus das Volume aus der gestoppten Sicherung, notfalls der Server-Snapshot. Gebraucht haben wir ihn nicht. Aber ohne ihn hätten wir den Wechsel nicht gemacht.

Kurz gesagt

Das Update selbst ist nicht schwer. Schwer ist, hinterher sicher zu sein, dass nichts still kaputt ist. Eine Generalprobe auf einer Kopie ohne Netz kostet einen Nachmittag und beantwortet die meisten Fragen vorher – den Rest, wie die signierten Wait-Webhooks, findet man nur durch Beobachten im Betrieb.

Wenn Sie eine selbst gehostete n8n-Instanz in Freiburg, der Ortenau oder anderswo betreiben und das 2.x-Update noch vor sich haben: Genau solche Umzüge gehören zu dem, was ich als n8n-Experte in Freiburg mache.

Denis Shokhirev, DennisCraft AI Studio, Freiburg im Breisgau

Read more

Computer-Use-Agenten scheitern an Pixeln: wie Sie auf stabile UI-Referenzen über Accessibility Trees umstellen und fehleranfällige Desktop-Automatisierung nicht mehr ständig reparieren

von Denis Shokhirev, Enterprise AI Architect aus Freiburg im Breisgau Ich bin Denis Shokhirev, Agentic AI Systems Architect in Freiburg im Breisgau, Germany, und bei DennisCraft AI Studio setze ich produktive KI-Systeme für DACH-B2B-Kunden auf Basis von Claude, Supabase, n8n, Doppler und selbst betriebenem Postgres um. Die teuersten Fehler in

By Denis Shokhirev

Компьютерные агенты ломаются на пикселях: как перейти на stable UI refs через accessibility tree и перестать чинить flaky desktop automation

Я Denis Shokhirev, Agentic AI Systems Architect из Freiburg im Breisgau, Germany, и в DennisCraft AI Studio я собираю production AI-системы для DACH B2B на Claude, Supabase, n8n, Doppler и self-hosted Postgres. Самая дорогая поломка в desktop automation, которую я вижу у клиентов, почти никогда не связана с моделью: агент

By Denis Shokhirev