[{"data":1,"prerenderedAt":432},["ShallowReactive",2],{"agmd-flowfuse-data-plane":3,"application-guide-nav":324},{"id":4,"title":5,"blurb":6,"body":7,"description":20,"extension":315,"guide":316,"meta":317,"navOrder":313,"navTitle":5,"navigation":318,"parent":319,"path":320,"seo":321,"slug":13,"stem":322,"__hash__":323},"applicationGuideDoc\u002Fapplication-guide\u002Fflowfuse\u002Fdata-plane.md","Data plane","Before you pick where things run, decide how data is handled. Two stores come built into every FlowFuse server install — the Team Broker and relational Tables — exposed to every instance with nothing extra to stand up. Everything else you bring your own: run it (a time-series DB, an existing database, a model) and expose it to the fleet over Project Link, no inbound ports. This is the data plane the architectures on the next pages all sit on.",{"type":8,"value":9,"toc":311},"minimark",[10,14,21,23,296],[11,12,5],"h1",{"id":13},"data-plane",[15,16,17],"p",{},[18,19,20],"strong",{},"Data plane — start here",[15,22,6],{},[24,25,26,104,167,236],"guide-tabs",{},[27,28,30,36,43,46,52,58,63,91,96],"guide-tab",{"label":29},"Relational",[15,31,32,35],{},[18,33,34],{},"Built in"," — ships with every FlowFuse server install; exposed to every instance.",[37,38],"flow-diagram",{":edges":39,":groups":40,":legend":41,":nodes":42},"[{\"from\":\"instances\",\"to\":\"tables\",\"label\":\"query & update\",\"accent\":\"slate\"}]","[{\"label\":\"Built into every FlowFuse server install\",\"accent\":\"green\",\"nodes\":[\"tables\"]}]","[{\"line\":\"slate\",\"label\":\"Authenticated · every instance reaches it\"}]","[{\"id\":\"instances\",\"label\":\"Instances\",\"sub\":\"App A · B · C\",\"accent\":\"indigo\",\"many\":true},{\"id\":\"tables\",\"label\":\"FlowFuse Tables\",\"sub\":\"relational\",\"accent\":\"green\"}]",[15,44,45],{},"A place for records that relate to each other — assets, config, users, orders — that you look up, join and update in place. It's FlowFuse Tables, built into every FlowFuse server install and exposed to every instance on the team.",[15,47,48,51],{},[18,49,50],{},"Use it when"," — The data has structure and relationships, and apps across the team should read and write the same store.",[15,53,54,57],{},[18,55,56],{},"How it works"," — FlowFuse Tables (managed PostgreSQL) via the Query node; because it ships with the server, any instance on the team reaches it natively over an authenticated connection.",[15,59,60],{},[18,61,62],{},"In FlowFuse",[64,65,66,73,79,85],"ul",{},[67,68,69,72],"li",{},[18,70,71],{},"FlowFuse Tables"," — managed PostgreSQL, built into every FlowFuse install",[67,74,75,78],{},[18,76,77],{},"Query node"," — read, join and update from any instance",[67,80,81,84],{},[18,82,83],{},"Exposed to the whole team automatically"," — nothing to stand up",[67,86,87,90],{},[18,88,89],{},"Also any external Postgres"," — same node",[15,92,93],{},[18,94,95],{},"Good to know",[64,97,98],{},[67,99,100,103],{},[18,101,102],{},"Watch out"," — not for high-rate timestamped streams; use the time-series target for those.",[27,105,107,112,119,122,127,132,136,156,160],{"label":106},"Broker \u002F UNS",[15,108,109,111],{},[18,110,34],{}," — ships with every FlowFuse server install; publish once, many subscribe.",[113,114],"arch-diagram",{":edges":115,":groups":116,":legend":117,":nodes":118},"[{\"from\":\"pub\",\"to\":\"broker\",\"label\":\"publish\",\"accent\":\"teal\",\"dashed\":true},{\"from\":\"broker\",\"to\":\"dashboard\",\"label\":\"subscribe\",\"accent\":\"teal\",\"dashed\":true},{\"from\":\"broker\",\"to\":\"historian\",\"accent\":\"teal\",\"dashed\":true},{\"from\":\"broker\",\"to\":\"other\",\"accent\":\"teal\",\"dashed\":true}]","[{\"label\":\"Built into every FlowFuse install\",\"accent\":\"teal\",\"nodes\":[\"broker\"]}]","[{\"line\":\"teal\",\"dashed\":true,\"label\":\"MQTT · publish once, many subscribe\"}]","[{\"id\":\"dashboard\",\"label\":\"Dashboard\",\"sub\":\"subscribes\",\"accent\":\"blue\",\"col\":1,\"row\":1},{\"id\":\"historian\",\"label\":\"Historian\",\"sub\":\"subscribes\",\"accent\":\"green\",\"col\":2,\"row\":1},{\"id\":\"other\",\"label\":\"Other app\",\"sub\":\"subscribes\",\"accent\":\"slate\",\"col\":3,\"row\":1},{\"id\":\"broker\",\"label\":\"Team Broker\",\"sub\":\"built in · UNS\",\"accent\":\"teal\",\"col\":2,\"row\":2},{\"id\":\"pub\",\"label\":\"Instance\",\"sub\":\"publishes\",\"accent\":\"indigo\",\"col\":2,\"row\":3}]",[15,120,121],{},"A real-time bus, not storage: one instance publishes to a topic, any number subscribe. It's the Team Broker, built into every FlowFuse server install — the backbone of a Unified Namespace.",[15,123,124,126],{},[18,125,50],{}," — Live data needs to reach many consumers at once, decoupled, as it happens.",[15,128,129,131],{},[18,130,56],{}," — The built-in Team Broker with publish \u002F subscribe nodes; because it ships with the server, every instance on the team can publish and subscribe over MQTT. Pair with Tables when you also need to keep history.",[15,133,134],{},[18,135,62],{},[64,137,138,144,147,153],{},[67,139,140,143],{},[18,141,142],{},"Team Broker"," — built into every FlowFuse install, no separate product to stand up",[67,145,146],{},"publish \u002F subscribe nodes",[67,148,149,152],{},[18,150,151],{},"Topic structure"," — your Unified Namespace",[67,154,155],{},"Exposed to the whole team; pair with Tables for history",[15,157,158],{},[18,159,95],{},[64,161,162],{},[67,163,164,166],{},[18,165,102],{}," — it carries data, it doesn't store it; write to Tables too if you need history.",[27,168,170,176,182,185,190,195,199,225,229],{"label":169},"Time-series",[15,171,172,175],{},[18,173,174],{},"Bring your own"," — external today; FlowFuse has no built-in time-series DB.",[37,177],{":edges":178,":groups":179,":legend":180,":nodes":181},"[{\"from\":\"db\",\"to\":\"hosted\",\"label\":\"Postgres wire\",\"accent\":\"slate\"},{\"from\":\"hosted\",\"to\":\"fleet\",\"label\":\"Project Link\",\"accent\":\"red\",\"dashed\":true}]","[{\"label\":\"External · where the readings live\",\"accent\":\"slate\",\"nodes\":[\"db\"]}]","[{\"line\":\"slate\",\"label\":\"Postgres wire\"},{\"line\":\"red\",\"dashed\":true,\"label\":\"Project Link · target is a Hosted Instance\"}]","[{\"id\":\"db\",\"label\":\"Time-series DB\",\"sub\":\"Timescale \u002F QuestDB\",\"accent\":\"slate\"},{\"id\":\"hosted\",\"label\":\"Hosted Instance\",\"sub\":\"connects & fronts it\",\"accent\":\"indigo\"},{\"id\":\"fleet\",\"label\":\"Instances\",\"sub\":\"query by time\",\"accent\":\"slate\",\"many\":true}]",[15,183,184],{},"A store built for a steady stream of timestamped readings — sensor data, telemetry, trends — written fast and queried by time. FlowFuse has no built-in time-series database, so you run one and expose it to the fleet.",[15,186,187,189],{},[18,188,50],{}," — The data is a continuous stream of timestamped values, written at high rate and queried by time window.",[15,191,192,194],{},[18,193,56],{}," — Run TimescaleDB, QuestDB or InfluxDB where you want. A Hosted Instance connects to it — Timescale and Quest speak the Postgres wire, so the Query node connects exactly like Tables; InfluxDB connects through its own nodes — and fronts it; other instances reach it over Project Link, which always calls a Hosted Instance, with no inbound ports.",[15,196,197],{},[18,198,62],{},[64,200,201,207,213,219],{},[67,202,203,206],{},[18,204,205],{},"External"," — FlowFuse has no built-in time-series DB today",[67,208,209,212],{},[18,210,211],{},"TimescaleDB \u002F QuestDB"," — speak the Postgres wire; Query node connects like Tables",[67,214,215,218],{},[18,216,217],{},"Hosted Instance"," — connects to it and fronts it for the fleet",[67,220,221,224],{},[18,222,223],{},"Project Link"," — reaches it with no inbound ports (targets a Hosted Instance)",[15,226,227],{},[18,228,95],{},[64,230,231],{},[67,232,233,235],{},[18,234,102],{}," — not part of FlowFuse; you run and expose it. Pair with the Team Broker for live + history.",[27,237,238,243,249,252,257,262,266,284,288],{"label":174},[15,239,240,242],{},[18,241,174],{}," — expose any other store or service to the fleet over Project Link.",[37,244],{":edges":245,":groups":246,":legend":247,":nodes":248},"[{\"from\":\"store\",\"to\":\"hosted\",\"label\":\"connects\",\"accent\":\"slate\"},{\"from\":\"hosted\",\"to\":\"fleet\",\"label\":\"Project Link\",\"accent\":\"red\",\"dashed\":true}]","[{\"label\":\"Wherever it lives · you run it\",\"accent\":\"slate\",\"nodes\":[\"store\"]}]","[{\"line\":\"slate\",\"label\":\"connects\"},{\"line\":\"red\",\"dashed\":true,\"label\":\"Project Link · target is a Hosted Instance\"}]","[{\"id\":\"store\",\"label\":\"Your store \u002F service\",\"sub\":\"SQL · ML · gateway\",\"accent\":\"slate\"},{\"id\":\"hosted\",\"label\":\"Hosted Instance\",\"sub\":\"connects & fronts it\",\"accent\":\"indigo\"},{\"id\":\"fleet\",\"label\":\"Instances\",\"sub\":\"queries it\",\"accent\":\"slate\",\"many\":true}]",[15,250,251],{},"Any other store or service FlowFuse doesn't provide — an existing SQL database, an ML model, a site gateway. You run it where it already lives and expose it to the fleet of managed instances over Project Link, with no inbound ports.",[15,253,254,256],{},[18,255,50],{}," — You need to reach a store or service that isn't built in and isn't a time-series DB — an existing database, a model, a gateway.",[15,258,259,261],{},[18,260,56],{}," — A Hosted Instance connects to the store or service and fronts it; other instances reach it over Project Link — which always targets a Hosted Instance — as a secure API \u002F MCP endpoint, with no inbound ports and no copy into a warehouse.",[15,263,264],{},[18,265,62],{},[64,267,268,273,278,281],{},[67,269,270,272],{},[18,271,217],{}," — connects to the store \u002F service and fronts it",[67,274,275,277],{},[18,276,223],{}," — calls a Hosted Instance (only Hosted Instances are callable targets)",[67,279,280],{},"Any SQL database, ML model or gateway",[67,282,283],{},"Exposed as a secure API \u002F MCP endpoint, no inbound ports",[15,285,286],{},[18,287,95],{},[64,289,290],{},[67,291,292,295],{},[18,293,294],{},"Good for"," — keeping data and services where they already live and exposing them securely to the fleet. FlowFuse doesn't care what the target is.",[297,298,300],"callout",{"icon":299},"i-lucide-git-branch",[15,301,302,305,306],{},[18,303,304],{},"Single service?"," Calling one external endpoint from a flow — an HTTP request or webhook to one system — is a Node-RED decision, not a platform data target. ",[307,308,310],"a",{"href":309},"\u002Fapplication-guide\u002Fnode-red\u002Fhandling-data\u002F","Node-RED guide →",{"title":312,"searchDepth":313,"depth":313,"links":314},"",4,[],"md","flowfuse",{},true,null,"\u002Fapplication-guide\u002Fflowfuse\u002Fdata-plane",{"title":5,"description":20},"application-guide\u002Fflowfuse\u002Fdata-plane","Qk71D8Ai3j7fDtwQ4ePjlhkYrIHofeKO2dfMAklYn1Y",[325,331,335,341,344,350,355,361,366,372,376,382,384,389,395,401,407,412,417,422,426],{"guide":316,"slug":326,"title":327,"navOrder":328,"parent":319,"blurb":329,"path":330},"overview","Overview",1,"The map of the FlowFuse guide — apps, architectures, and a worked example.","\u002Fapplication-guide\u002Fflowfuse\u002Foverview\u002F",{"guide":332,"slug":326,"title":327,"navOrder":328,"parent":319,"blurb":333,"path":334},"node-red","The map of the Node-RED guide — the pattern families that turn an app into a clean flow.","\u002Fapplication-guide\u002Fnode-red\u002Foverview\u002F",{"guide":316,"slug":336,"title":337,"navOrder":338,"parent":319,"blurb":339,"path":340},"foundations","Foundations",2,"The foundation to build on: what FlowFuse is, its core pieces, and how code is shared across teams.","\u002Fapplication-guide\u002Fflowfuse\u002Ffoundations\u002F",{"guide":332,"slug":336,"title":337,"navOrder":338,"parent":319,"blurb":342,"path":343},"The handful of concepts you need to build with Node-RED, and how they fit together.","\u002Fapplication-guide\u002Fnode-red\u002Ffoundations\u002F",{"guide":316,"slug":345,"title":346,"navOrder":347,"parent":319,"blurb":348,"path":349},"app-delivery-methods","App delivery methods",3,"Two different units of code, delivered two ways. Ship the whole app — a complete, versioned project promoted through environments — or publish one reusable piece — a package the whole team installs and upgrades in one place. Pick by what you're shipping: the app, or a part of it.","\u002Fapplication-guide\u002Fflowfuse\u002Fapp-delivery-methods\u002F",{"guide":332,"slug":351,"title":352,"navOrder":347,"parent":319,"blurb":353,"path":354},"patterns","Patterns","The moves that turn an architecture into a clean, reusable flow — find the seams and reuse well, then handle data on the right paths.","\u002Fapplication-guide\u002Fnode-red\u002Fpatterns\u002F",{"guide":316,"slug":356,"title":357,"navOrder":358,"parent":345,"blurb":359,"path":360},"hardware-apps","Hardware apps",3.1,"The three shapes a FlowFuse app takes when it runs on a device. Pick by how much varies per site: nothing (Packaged App), a few settings (Configurable App), or you assemble it yourself (Edge Building Block).","\u002Fapplication-guide\u002Fflowfuse\u002Fhardware-apps\u002F",{"guide":332,"slug":362,"title":363,"navOrder":358,"parent":351,"blurb":364,"path":365},"design-patterns","Design patterns","The structural choices you select for a flow: find the seams it breaks into, then reuse each piece at the lightest level that solves it — link in\u002Fout, link call, subflow, or packaged node.","\u002Fapplication-guide\u002Fnode-red\u002Fdesign-patterns\u002F",{"guide":316,"slug":367,"title":368,"navOrder":369,"parent":345,"blurb":370,"path":371},"software-apps","Software apps",3.2,"The three shapes a FlowFuse app takes when it runs on the platform. Pick by what it needs: a headless job (Packaged App), a user-facing app driven by data (Data-Driven App), or a reusable piece other apps embed (Shared Building Block).","\u002Fapplication-guide\u002Fflowfuse\u002Fsoftware-apps\u002F",{"guide":332,"slug":373,"title":374,"navOrder":369,"parent":351,"blurb":375,"path":309},"handling-data","Handling data","Classify each signal by shape, purpose and direction, then pick the methods it needs — separate the paths, pace the flow, hold state in context, and manage config. The methods you select to move a flow's data.",{"guide":332,"slug":377,"title":378,"navOrder":379,"parent":351,"blurb":380,"path":381},"good-form","Good form",3.3,"A clean flow isn't luck — it's a handful of habits. Wire for reading, lay it out on a grid, decouple UI from logic, catch errors where you can see them, and keep data on a stable contract. Follow these and a flow stays readable, reusable, and out of spaghetti.","\u002Fapplication-guide\u002Fnode-red\u002Fgood-form\u002F",{"guide":316,"slug":13,"title":5,"navOrder":313,"parent":319,"blurb":6,"path":383},"\u002Fapplication-guide\u002Fflowfuse\u002Fdata-plane\u002F",{"guide":332,"slug":385,"title":386,"navOrder":313,"parent":319,"blurb":387,"path":388},"worked-examples","Worked examples","Turn an app concept into a Node-RED flow — or a few — leaning on the design patterns and data handling. The method, then the OEE apps end to end.","\u002Fapplication-guide\u002Fnode-red\u002Fworked-examples\u002F",{"guide":332,"slug":390,"title":391,"navOrder":392,"parent":385,"blurb":393,"path":394},"oee-edge-aggregator","OEE - Edge Aggregator",4.1,"The edge app from the OEE use case as a Node-RED flow — a straight-line flow packaged as a subflow and configured per line (its PLC tags, via a config UI and a get-config node), with the data treated as a stream and its counts held in context.","\u002Fapplication-guide\u002Fnode-red\u002Foee-edge-aggregator\u002F",{"guide":332,"slug":396,"title":397,"navOrder":398,"parent":385,"blurb":399,"path":400},"oee-central-dashboard","OEE - Central Dashboard",4.2,"The cloud app from the OEE use case as a Node-RED flow — one link out fanning to two link ins on separate tabs (dashboard and batched history), so the live and history paths stay separate and easy to read.","\u002Fapplication-guide\u002Fnode-red\u002Foee-central-dashboard\u002F",{"guide":316,"slug":402,"title":403,"navOrder":404,"parent":319,"blurb":405,"path":406},"architectures","Architectures",5,"Every FlowFuse deployment is the same building blocks arranged for where it runs — pick the world you're designing for.","\u002Fapplication-guide\u002Fflowfuse\u002Farchitectures\u002F",{"guide":316,"slug":408,"title":409,"navOrder":410,"parent":402,"blurb":319,"path":411},"it-architectures","IT architectures",5.1,"\u002Fapplication-guide\u002Fflowfuse\u002Fit-architectures\u002F",{"guide":316,"slug":413,"title":414,"navOrder":415,"parent":402,"blurb":319,"path":416},"ot-architectures","OT architectures",5.2,"\u002Fapplication-guide\u002Fflowfuse\u002Fot-architectures\u002F",{"guide":316,"slug":418,"title":419,"navOrder":420,"parent":402,"blurb":319,"path":421},"iiot-architectures","IIoT architectures",5.3,"\u002Fapplication-guide\u002Fflowfuse\u002Fiiot-architectures\u002F",{"guide":316,"slug":385,"title":386,"navOrder":423,"parent":319,"blurb":424,"path":425},6,"Start from a use case, break it into apps, and draw the architecture that ties them together — the same method a FlowFuse Proof of Value runs.","\u002Fapplication-guide\u002Fflowfuse\u002Fworked-examples\u002F",{"guide":316,"slug":427,"title":428,"navOrder":429,"parent":385,"blurb":430,"path":431},"worked-example","OEE, end to end",6.1,"One use case — OEE across three lines — broken into two apps and two shared services, then drawn out end to end.","\u002Fapplication-guide\u002Fflowfuse\u002Fworked-example\u002F",1787843651760]