On this page · 7 sections

A number without its machine is not a number. These are the measurements of node scripts/bench-agent.js on the machine below, run on 2026-09-22 with agent 1.18.0: the agent as a customer runs it, a simulator source of 2000 tags at 100 ms, a Modbus TCP emulator of 400 holding registers polled in 4 blocks every 50 ms, and 20 WebSocket clients subscribed to every simulator tag, for 10 s. Everything on one machine: the clients share the agent's CPU, so the figures are a lower bound on the agent and an upper bound on what one network carries.

The machine

CPUIntel(R) Core(TM) Ultra 7 255U, 14 logical cores
Memory31 GB
Platformwin32 10.0.26200
Node.jsv24.18.0

Delivery

Samples delivered a second, all clients366,927
Per client a second18,346 of 20,000 produced (92 %)
Agent CPU while delivering0.3 cores
Agent resident memory125 MB with 2400 tags and 20 clients

A share under 100 % means the agent's single thread could not serialise every sample for every client in time and the WebSocket buffers grew; the samples are not lost to the hub (the latest value is what a screen shows), but a screen sees fewer of them. The sizing rule that follows: tags × clients × updates a second ≈ 366,927 on a machine like this one; a station with 500 tags at 500 ms and 10 screens is at 10,000, well inside.

Modbus

Poll requests a second68 of 80 asked (4 blocks of 100 registers every 50 ms)
Registers a second6,759

Against the emulator, on the same machine; a PLC on a network answers in its own time, and one request per block per poll is the point of the block reads.

A write, round trip

Writes measured200
Median0.6 ms
95th percentile1 ms
99th percentile17.1 ms

From the client's write over the WebSocket to the confirmed sample back at the client, while the 20 clients were being fed. The simulator confirms at once; a PLC or an instrument adds its own answer time, and a poll-based source the rest of its interval.

The API and connections

GET /api/tags with 2,400 tags12.9 ms median, 28.9 ms at the 95th percentile
200 WebSocket clients connecting at once140 ms until all were open

The designer and the app with a large project

Measured by node scripts/bench-designer.js on 2026-09-22 in Chromium (puppeteer), headless on the same machine: a project with a page of 300 components (tiles, gauges, LEDs, readouts, tanks, every one bound to a simulator tag), 20 further pages of 30, and a dataflow diagram of 300 nodes and 398 wires.

The designer opens on the 300-component page1353 ms from navigation to the last cell (75 ms to the document)
Switching to a 30-component page507 ms
Switching back to the 300-component page1460 ms
Selecting a component (the inspector generated)23 ms
Drawing the 300-node diagram687 ms
The published app opens on the same page1841 ms, 24 MB of JavaScript heap

An operator screen is rarely this dense; a page of 30 to 60 components is the usual one, and the figures scale with the count. The diagram's 300 nodes ran at their loop's period without falling behind.

Running it yourself

node scripts/bench-agent.js --tags 2000 --clients 20 --interval 100 --seconds 10 --doc
node scripts/bench-designer.js --components 300 --pages 20 --nodes 300 --doc

The results go to studio/bench/agent.json; --doc rewrites this page from them. A station's real figure is the one measured on that station with its instruments: run the bench there before sizing.