How a flow works
A flow is nodes and the connections between them. Execution starts at the trigger and follows the connections while there are any.
Connections and branches
A connection leaves one node and leads to the next. A node with no incoming connection never runs — the trigger aside.
Some nodes have more than one exit:
Condition—trueandfalseSwitchCase— one exit per case- any node — a separate
errorbranch when it fails
The error branch is what separates a sturdy flow from a brittle one. Without it, one failing node stops the whole run.
Retries and timeouts
Each node has its own settings: how many times to retry, how long to wait between attempts, and when to call it stuck. Retrying suits network calls; retrying a write can create a duplicate, so prefer upsert with a key there.
How many nodes a flow holds
A flow takes up to 200 nodes. The reason is not speed: a larger one stops being workable — you cannot take it in at a glance, check it, or fix it when it breaks. If you reach the limit, move a finished part into its own flow and call it with a SubFlow node, so each piece can be run and checked on its own. Variables are capped at 100 per flow.
The budget of one run
One run cannot take more than 1000 steps — that is the guard against an endless loop. The budget is shared with every sub-flow it calls, so nesting cannot get around it. Sub-flows cannot call each other in a circle, and nesting stops at three levels.
History
Every run is recorded: input, node outputs, timing, failure. The last 10,000 runs per flow are kept.
Replay on the current version
A run card has a "Replay" button. The input of that run goes through the flow as it is now, and every node output is then compared with the original: unchanged, changed (with the fields that differ), new, gone, failed, fixed, stub (in a dry replay the node had no recorded output). A dry replay takes its outputs first from the run being replayed. Fields that change on their own, such as timestamp, id, messageId or durationMs, do not count as a change. A replay is dry by default, so external systems are not touched; a real replay has to be switched on explicitly. If the input of that run had fields masked before saving, the replay dialog lists them: fill one in to replay with the real value, or leave it empty and the mask goes through as it is. Replays are marked in the history.
Import from n8n
An n8n export (JSON with nodes and connections) can be imported with the same "Import" button on the flows page: the format is recognised automatically. Webhook, schedule, HTTP request, IF with true/false branches, Set, Slack, Telegram, email, Google Sheets, Postgres and MySQL, Wait, Merge, Split in Batches and the webhook response are transferred; No Operation is skipped with its link passed through. Expressions like $json.x, $node["Name"].json.x and $('Name').item.json.x become input.x and outputs.<id>.x. Nodes without a counterpart, such as Code and Function, are replaced by a TextFormatter placeholder with a note; credentials are not transferred, instead the flow gets secret variables such as SLACK_TOKEN, TELEGRAM_TOKEN and DB_URL to fill in. The notes are shown before anything is created, and the flow is created switched off.
Drift radar
After every real run the shape of the answer of external nodes is remembered: HttpRequest, Database, SqlQuery, GoogleSheets, VectorSearch. Only field names and their types are stored, never values. Every night yesterday's shape is compared with the shape of the previous week. When a field that a later node reads has disappeared or changed type, a warning with both node names appears in the checks panel, and the notification webhook (if enabled) receives a message marked drift. The warning closes itself when the field comes back, or with "Mark as resolved". The comparison needs at least three answers from the previous week, so a new flow cannot raise an alert before a day has passed.
What happened and what changed, in words
A run card has a "What happened?" button. The assistant reads the steps of the run and retells them in a few plain sentences: what came in, what was decided, where it went, where it stopped. The answer is stored with the run, so a second click costs nothing. In the versions panel every version has "What changed": first a list of changes against the previous version (nodes, settings, links, variables without values), and "Explain in words" turns it into a short text. Both explanations are written in the interface language and count as assistant calls.
Fixing failures with the assistant
A failed run has a "Suggest a fix" button. The assistant sees the node that failed, its config, the data it received, the error text and the reference for that node type, and returns a corrected config with a plain-language explanation. It changes one node only and never sees secrets: variable values are not shown to it, and masked input fields reach it as masks. "Apply as a new version and check" saves a separate flow version and immediately replays the same input dry, so you see whether it helped. If not, ask again, up to three times per run. Each request counts as an ordinary assistant call.
Fixtures
A good run can be marked as a fixture with a button in the history. Its input and every node output are kept. After each save of the flow the fixtures are replayed dry on the new version, and the "Fixtures" button in the editor shows the outcome: how many are unchanged, changed or failed. Clicking a fixture in the panel opens the same per-node diff as a replay. A dry run or a failed run cannot become a fixture. Up to 10 fixtures per flow. The check runs dry and counts against the run quota like any dry run. Outputs of side-effect nodes come from the fixture itself, so the check compares only what the flow itself does.
Dry run
The test run form has a "Dry run" switch. In a dry run the nodes that reach the outside world do not execute: HttpRequest with a method other than GET, writes in Database, SqlQuery and GoogleSheets, FileWriter, Email, Telegram, Slack, and also LlmPrompt and Agent, which cost tokens. Instead of acting, each such node answers with the output recorded on the last real run of that same node, and the step is marked ⟲ in the results. The last completed step of that node from any real run is used, even when that run failed further down. A node that has never completed for real answers with a stub carrying dryRun: true, so the nodes after it may fail on missing fields. That is expected: one real run first, then as many dry runs as you like. Delay does not wait in a dry run, and nested flows run dry as well. Dry runs are marked in the history, send no notifications and stay out of analytics.
Checks
The Diagnostics tab at the bottom of the editor shows what we can find in the flow ourselves: broken expressions, reads of a node that has not run, empty required fields, nodes with no connections. It is the same check we run on flows the assistant builds.