← Articles
Modbus/7 min read/ views

How Many Modbus TCP Clients Can One PLC Actually Take?

Modbus TCP devices cap simultaneous connections lower than you think. Inventorying clients, reading real socket behaviour, and protecting the HMI.

ModbusSCADANetworkingTroubleshootingProject Notes

The failure that sends me back to a site is almost never a bad register map. It's the fifth thing that connected to the PLC on port 502. The bench test worked because one laptop polled one device. Then the HMI server, the standby HMI, the historian, an engineering laptop that got left running, and a vendor's diagnostic tool over VPN all pointed at the same address — and now the operators are watching stale data and blaming the network.

Modbus TCP hides this. The MBAP header carries a transaction identifier, so a single socket can have several requests in flight, and a client can happily open a fresh socket for every poll if you let it. Nothing in the protocol tells you how many sockets the server will tolerate. That number is a device implementation detail, and it is usually smaller than anyone assumes: cheap power meters and serial-to-Ethernet gateways often cap at 1 to 4 simultaneous connections, and even PLC Ethernet modules that advertise a big number frequently serialize the work behind them.

Count sockets before you count tags

A tag list tells you nothing about connection pressure. Before I look at a single register I write down who opens a socket:

ClientWhy it connectsWhat bites you
Primary SCADA serverDisplays, alarms, operator writesMust stay connected and deterministic
Standby SCADA serverFailoverActive-active doubles the request rate
Historian interfaceTime-series collectionRe-polls the same registers the SCADA already has
Engineering laptopOnline troubleshootingGrabs a scarce slot and gets left plugged in
MES / reporting connectorProduction dataAdded months after handover, off the drawing
Vendor remote toolService and diagnosticsReconnects aggressively over a flaky VPN

For each one I record the source IP, the software, its polling role, and — the column people skip — whether it is allowed to write. Do this on paper at commissioning and you never have the argument later where nobody knows which system opened the third socket.

The datasheet says "supports Modbus TCP" and stops there

That line means nothing for capacity planning. During commissioning I actually test:

  • How many simultaneous TCP connections the device accepts.
  • What happens at the limit — does it refuse the new connection, or silently drop the oldest one? Last-connection-wins eviction is the nasty one, because the tool you just plugged in kicks out the HMI that was working.
  • Whether it processes requests in parallel or serializes them internally. A device can accept eight sockets and still service one PDU at a time.
  • How long a half-open socket lingers after an ungraceful disconnect. If the device relies on TCP keepalive rather than an application idle timeout, a yanked cable can hold a slot for minutes.
  • Whether a write from any connected client is accepted with no ownership rule at all. Most low-end devices will happily take a 0x06 write from whoever sends it.

And the one everybody forgets on a gateway: the Unit Identifier in the MBAP header is how the bridge routes to a downstream serial slave. Ten Ethernet clients can connect cleanly and still pile onto a single RS-485 line at 19200 baud. The TCP side looks healthy; the serial side is timing out. You are not planning Ethernet sockets there, you are planning airtime on one two-wire bus.

Give the data one owner

For anything the operators actually watch, I want one authoritative poller. The SCADA server reads the PLC, and the historian, displays, and reports take that data through the SCADA platform or an OPC UA layer — not by opening their own sockets to the PLC. It is the difference between one well-understood client and a scrum.

Direct polling by several systems is fine, but only when all of these hold:

  • The device has proven it survives the combined request rate under load, not on the bench.
  • Read ranges are coordinated so you're not paying for the same holding registers three times.
  • Write permission lives with exactly one system — the one that owns operator commands.
  • Maintenance tools connect only while someone is actively troubleshooting, and disconnect after. "I'll leave it running so I don't have to reconnect" is how the fourth slot disappears.

If a historian genuinely must poll direct, put it in a slow scan group — a few seconds, not sub-second. A background report collector has no business competing with command feedback and alarms for the same socket budget.

The Modbus Messaging on TCP/IP Implementation Guide (v1.0b, Modbus.org) is explicit that a client should keep one TCP connection open to a server and reuse it for many transactions rather than opening a connection per request. Stacks that open and close a socket every poll burn through the connection table and leave TIME_WAIT sockets everywhere. If you inherit one of those, that alone can look like a connection limit.

Redundancy quietly doubles the load

Redundant SCADA is where the request rate sneaks up on you. Active-active means both nodes read every device, all the time — fast failover, double the traffic. Warm standby cuts the traffic but you have to prove it ramps up fast enough when the primary drops. Cold standby saves the most but tends to expose connection and cache bugs at the worst possible moment, mid-failover.

Whatever you pick, test it against the real device count. A redundancy test with one PLC on the bench tells you nothing about a line with fifty gateways, because the failure mode you care about is the socket table filling up, and that only shows up at scale.

When it looks like a network fault but isn't

Connection-limit problems love to disguise themselves as flaky Ethernet. The tell-tale signs:

  • A new client connects and an existing HMI immediately goes to bad quality.
  • Engineering software only works after someone stops the historian service.
  • The first few devices on a gateway respond; everything past a certain point times out.
  • A pulled cable leaves the device refusing new connections for several minutes.
  • A packet capture shows the TCP handshake completing, then no Modbus response at all — and crucially, no exception code, because the request never reached application handling to generate one.

When you see these, do not reach for higher scan rates or more retries. That is the instinct, and it makes the contention worse — you're adding requests to a device that is already out of room.

The drill before handover

Run this with the real clients, in the real operating state, before you sign off:

  1. List every planned client and its source IP.
  2. Connect them all as they'll run in production.
  3. Read the current connection count off the PLC, gateway, or firewall if any of them expose it.
  4. Start the historian or reporting connector and watch SCADA quality — did anything flicker?
  5. Open an engineering tool and confirm it does not evict the HMI's socket.
  6. Pull a client's cable and time how long the stale socket takes to clear.
  7. Run a failover and measure the extra request rate it adds.
  8. Try a write from a path that shouldn't have write access, and confirm it's blocked.

Keep the results in the project file. The next person who wants to bolt on a reporting connector needs to know what the original capacity and ownership model were — and if they don't, you'll get the call.