Design patterns — pick how a flow is structured and reused
A design pattern is a structural choice you make for a piece of a flow. Building a flow you'll select one or more: first find the seams — the components the flow really breaks into — then, for each piece worth reusing, pick the level of reuse that fits. Reuse is a ladder — link in/out → link call → subflow → palette node — and each rung up buys more reuse but costs more to build and maintain, so climb only when the rung below won't do.
Name the pieces first — before any reuse, find the components hiding in the flow and draw a box around each.
Most spaghetti is three or four well-defined components that were never named. A giant flow is bad because it has no seams: you can't reuse, test, or hand off part of a blob, and any edit means reading the whole tab. Naming the structure is the fix — not tidier wires.
IngestNormalizeEnrichPublish
Look for one of these and box it off:
A repeated cluster — the same three or four nodes appearing in more than one place.
A logical stage — ingest, normalize, enrich, publish; each a bounded step with a clear input and output.
A bounded responsibility — one thing the piece owns from end to end.
A reuse magnet — a piece other flows will obviously want.
Once the seams are named, each becomes a candidate for reuse — and how you reuse it is the choice in the tabs that follow. A piece you'll only ever use once still earns its box; it just stays a plain seam.
Route within one instance — local · organization, not reuse.
Link in and link out route messages between points and tabs inside a single Node-RED instance, without dragging a wire across the canvas. One link out can feed many link ins — one producer, many consumers — so it's the clean way to fan a message out to several independent paths.
linkproducerone sourcelink outbroadcastlink inconsumer Alink inconsumer Blink inconsumer Clink out → link in
Nothing is packaged or reused, though — the message just teleports to the matching link.
Select it when — you need to tidy wiring, route between tabs, or fan one message out to several consumers. It's the bottom rung: routing and organization, no reuse of logic.
Not this when — you're trying to share work. The moment more than one path needs the same logic or resource, climb to a link call.
Stays local — link in/out never leave the instance and distribute nothing.
A shared, returning service — local · one instance.
Turn a link-in / link-out pair into a callable service: a piece of work exposed once that any path calls and that returns the result to whoever called it, with no central router to build. It's the workhorse for shared services inside one instance — a database pool, a model call, a broker connection, a common transform.
Shared service · every path calls this one link incallreturnhttp ina requestlink callcalls the servicehttp responsethe end · sends resultlink inservice entrySQL poolone shared connectionlink outreturn modecall / return
Select it when — more than one path needs the same resource or logic and you don't want a copy per path. Each path calls the one shared service, the result comes back, and the path finishes at its own sink — an http response here. No funnel: the shared service has exactly one wire in.
The trade-off — every caller shares one configuration. That's the point when the config is fixed; it's the limit when each use needs its own settings — which is when you climb to a subflow.
Stays local — reuse within one instance; it doesn't package or distribute.
A packaged set of actions, with its own config — cross-instance.
A subflow bundles a set of actions — several nodes — into one reusable node you can drop into a flow many times, each instance carrying its own configuration. Unlike a link call, which shares one fixed config, a subflow is a packaged assembly that varies per drop, and it travels between Node-RED instances.
Subflow · a set of actions packaged into one node, authored onceReused · that one node dropped in, each with its own configpackaged as one nodevalidatetransformpublishsubflowconfig Asubflowconfig Bsubflowconfig C
Select it when — a piece needs per-instance config (the same logic, different settings each place), or you need to reuse it across other Node-RED instances. Start as a link call and promote to a subflow only once it earns that.
The trade-off — heavier than a link call: each instance duplicates its connections, and defaulting to subflows for everything adds indirection. Use it for genuine per-instance reuse, not as the default.
Real packaged code — distributed.
The top rung: package a piece as an installable palette node — real code, versioned and installed like any library dependency. It's the same custom node the FlowFuse app delivery methods publish for reuse across apps, and the point where Node-RED reuse hands off to the FlowFuse guide's distribution story.
Select it when — a piece is used across many projects or teams and deserves to be versioned, installed, and upgraded like a dependency — not copied, and beyond what a shared subflow can carry.
The trade-off — it's real code with a real release cycle: a package to build, test, and maintain. The most powerful reuse and the most to own. Don't take this rung until link call and subflow genuinely can't cover it.