MQTT at 500 kbps: Bandwidth Is Set by Change Rate, Not Tag Count

Daniel Price9 min read
Industrial NetworkingOther ManufacturerTechnical Reference
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Where does the packet go before it hits the broker?

Follow the packet. A tag changes in the PLC. The edge gateway polls it over the local fieldbus at whatever scan rate you configure, stores the sample, and at the next publish interval builds one MQTT PUBLISH containing every tag that changed since the last push. That PUBLISH leaves the gateway over the site LAN, enters the satellite modem, crosses the RF hop, lands at the ground station, transits the carrier's backbone, and terminates on the broker's TCP port (1883 plain, 8883 TLS). Subscribers on the central server receive it from the broker over their own, usually fast, link.

Only one hop in that chain is constrained: the RF segment at roughly 500 kbps. Everything else runs at LAN or backbone speed. So the sizing question reduces to one number: how many bytes per second cross the RF hop in steady state, and how large is the worst-case burst. For 50 to 100 tags with 10 to 20 changing every few seconds, both numbers are small. The checks below take the readings in order, from layer one upward.

Check 1: Is the link actually delivering 500 kbps?

Layer one first. A satellite terminal rated "up to 500 kbps" sells you a ceiling, not a floor. Before touching MQTT settings, take three readings from the modem's status page or a throughput test to the broker's host:

Reading What it means Next check
Sustained upload throughput Uplink is the direction your PUBLISH traffic uses; the advertised rate is often the downlink figure If well below 500 kbps, resize using the measured figure in Check 2
Round-trip latency Geostationary hops add several hundred milliseconds per round trip; low-earth-orbit constellations far less. Latency sets QoS handshake and TCP connect cost, not throughput Feeds keep-alive and QoS selection in Check 4
Packet loss / link drops per day Each drop forces TCP reconnect, MQTT CONNECT, and a full BIRTH republish Feeds the BIRTH burst sizing in Check 3

Coverage is also a layer-one property. Constellation services are region-gated: polar coverage was not operational at the time the low-cost terminals under $10K were evaluated, and orders in uncovered regions do not ship until coverage exists. Mobile equipment that moves between covered and uncovered areas needs the store-and-forward behavior described in Check 5, not more bandwidth.

Check 2: How many bytes does steady state actually move?

MQTT was built for exactly this link class. The edge publishes by report-by-exception: after the initial connection it sends only tags whose values changed, not the whole tag list. Tag count therefore drops out of the steady-state calculation; only the change rate and per-change payload matter.

Worked estimate with labeled assumptions:

  • Assumption A: 20 tags change every 2 s (upper end of "10 to 20 changing every few seconds").
  • Assumption B: 100 bytes per tag change including metric name, value, timestamp, and MQTT/TCP/IP framing, uncompressed and without aliases. Read the actual figure from your gateway's transmission diagnostics or a packet capture; this is a planning placeholder.
Payload rate = 20 tags x 100 B / 2 s = 1,000 B/s = 8 kbps
Link budget  = 500 kbps
Utilization  = 8 / 500 = 1.6 %

Even if Assumption B is off by a factor of five, steady state stays under 10% of the link. Two settings cut it further:

Setting Effect on the wire Trade-off
Tag aliases Replaces the full metric name string with a short numeric alias after BIRTH; saves the name length on every subsequent change Subscriber must hold the alias map from the BIRTH; a missed BIRTH forces a rebirth request
gzip compression Compresses the payload block of each PUBLISH; most effective on batched pushes with repeated structure Small CPU cost on the edge; negligible gain on single-tag payloads
Publish interval 5-10 s or longer Batches more changes into one PUBLISH, amortizing TCP/IP and MQTT fixed header cost Live-view update latency equals the interval (see Check 5)

If the measured payload rate exceeds about 20% of measured uplink throughput after these settings, the change rate is higher than described; move to Check 6. Otherwise continue to the burst case.

Check 3: How big is the BIRTH burst?

The largest single transmission on the link is the BIRTH message sent at connection: every tag with its current value, data type, and metadata in one PUBLISH. With 100 tags this is the worst case, and it repeats after every link drop.

Estimate with labeled assumption C: 150 bytes per tag in BIRTH (name, type, value, properties).


Add one TCP handshake and one MQTT CONNECT/CONNACK round trip, each costing the link's round-trip latency from Check 1. On a geostationary hop the BIRTH completes in low single-digit seconds; on a low-earth-orbit link, under a second. Neither approaches saturation. The BIRTH matters only if the link flaps repeatedly: a link that drops every minute spends measurable time re-sending BIRTH and the historian sees gaps. gzip applies to the BIRTH as well and gives its largest saving there because the payload is big and repetitive.

Check 4: What do QoS and keep-alive cost?

Quality of service changes the packet count per published message, not the payload size:

QoS Packets per publish Round trips on the slow hop Use when
0 1 (PUBLISH) 0 Live display of fast-changing values where the next sample supersedes a lost one
1 2 (PUBLISH, PUBACK) 1 Historian and alarm data that must arrive at least once
2 4 (PUBLISH, PUBREC, PUBREL, PUBCOMP) 2 Rarely justified on a high-latency link; each publish is held open for two full round trips

At the payload rates in Check 2, QoS 1 acknowledgment traffic is a few bytes per publish and irrelevant to bandwidth. What QoS 2 costs is time: with several hundred milliseconds per round trip, the broker-side completion of each message takes over a second, and the edge's in-flight window fills if the publish rate is faster than the handshake completes. Use QoS 1 for batched data and reserve QoS 2 for nothing on this link unless a specific downstream consumer demands exactly-once semantics.

Keep-alive is a 2-byte PINGREQ/PINGRESP pair. Set the interval long enough that idle periods do not generate pings faster than real data, but short enough that the broker detects a dead link and publishes the DEATH certificate within your alarm response requirement.

Check 5: Does the publish rate hide history or writes?

Two behaviors are decoupled from the publish interval and are the most common source of misdiagnosis on slow links.

Local history.The gateway's poll rate against the PLC is independent of the MQTT publish rate. The historian at the center sees full resolution; only the live view lags by up to one publish interval. If history shows gaps equal to the publish interval, the gateway is configured to publish only the latest value rather than buffered samples; correct that in the transmission settings rather than shortening the interval.

Writes to the remote device. A write from the central HMI travels the reverse path immediately on the same TCP connection; it does not wait for the next publish window. Push a start command and the remote motor starts as fast as the link latency allows. What is delayed is the feedback tag: the running-state bit changes at the PLC, the gateway picks it up at the next poll, and it goes out on the next scheduled PUBLISH. With a 30 s interval the operator sees confirmation anywhere from a fraction of a second to 30 s later, depending on where in the cycle the write landed. If operators report "the command is slow", measure the actual command arrival at the PLC before touching the interval; the fix for slow-looking feedback is a shorter interval or a dedicated fast-publish group for command feedback tags, not more bandwidth.

Symptom Likely cause Check
Live values update in steps of the publish interval Expected behavior of batched publish Shorten interval or add a fast-publish group for critical tags
Historian has gaps equal to the publish interval Gateway publishing latest value only, not buffered samples Enable history/store-and-forward in transmission settings
Full tag list arrives repeatedly Link drops forcing BIRTH republish Check 1 loss reading; RF installation
Publishes queue and back up QoS 2 on a high-latency link, or measured uplink far below 500 kbps Check 4, then Check 1 throughput
Commands appear slow but feedback is what lags Feedback tag waiting for next publish Timestamp the write at the PLC; confirm command arrived immediately

Check 6: Do you need a bigger pipe at all?

Reach this branch only if Check 2 shows utilization above roughly 20% after aliases and compression, or if the application adds payloads MQTT batching cannot shrink (camera streams, file transfers, remote desktop). At that point the options split on cost and coverage rather than protocol:

  • Terminals under $10K rated up to 500 kbps carry the described 50-100 tag load with margin. Higher-rate antennas at the $50K level cost more than the automated equipment they serve and are not justified by tag traffic.
  • Business-class low-earth-orbit service advertised at 300-500 Mbps for roughly $500/month after hardware is a different class of link and removes the bandwidth question entirely, subject to the coverage gating in Check 1. Where coverage exists for your operating areas, this is the fallback when payload growth is expected.

For the stated load, the 500 kbps terminal is the correct choice; the protocol configuration in the next section is what makes it work.

What is the procedure and how do you verify it?

  1. Measure uplink throughput, round-trip latency, and daily drop count on the installed terminal (Check 1). Record them; they are the baseline for every later comparison.
  2. Set the MQTT publish interval to 5-10 s for the general tag group. Create a separate fast group (1-2 s) containing only command feedback tags if operator response time requires it.
  3. Enable tag aliases and gzip compression in the transmission module.
  4. Set QoS 1 for historian and alarm data, QoS 0 for display-only fast values. Do not use QoS 2.
  5. Enable store-and-forward so samples collected during an outage flush on reconnect with original timestamps.
  6. Connect and capture one BIRTH plus ten minutes of steady state at the broker (broker logs or a packet capture on the broker host).

Verification, in order:

  1. From the capture, compute actual bytes per second in steady state and compare to the Check 2 estimate; replace Assumption B with the measured figure and recompute utilization against measured uplink, not the 500 kbps rating.
  2. Confirm the BIRTH size and the time from TCP SYN to BIRTH arrival; it should be on the order of the Check 3 estimate plus two round trips.
  3. Issue a write from the central HMI while timestamping at the PLC; the command must land within one link round trip, with feedback arriving no later than one publish interval plus one poll period.

FAQ

Can MQTT run reliably on a 500 kbps satellite link with 100 tags?

Yes. With report-by-exception, only changed tags are sent after the initial BIRTH; 20 tags changing every 2 s at an assumed 100 bytes each is about 8 kbps, under 2% of the link. Aliases and gzip reduce it further.

Does a slow MQTT publish rate delay writes to the remote PLC?

No. Writes travel immediately over the same connection; only the feedback tag waits for the next scheduled publish, so with a 30 s interval confirmation can lag up to 30 s while the command itself arrived within one round trip.

Does QoS level matter for bandwidth on a low-speed MQTT link?

Bandwidth barely changes, since PUBACK and the QoS 2 handshake packets are a few bytes each; latency is what grows. QoS 2 holds each message open for two round trips, which on a high-latency satellite hop exceeds a second per publish. Use QoS 1 for logged data and QoS 0 for display values.

Back to blog