MQTT bridging connects two brokers so that messages on selected topics flow from one to the other automatically. By the end of this guide you will understand when a bridge makes sense, how topic remapping and loop prevention work, and you will have a working Mosquitto bridge config and a Node-RED alternative that forward local data to a cloud broker.
What MQTT Bridging Actually Does
A bridge is not a special protocol. One broker (or a helper program) simply opens an ordinary MQTT client connection to another broker, subscribes on one side and republishes on the other. From the remote broker's point of view, the bridge is just another client with a username, password and client ID.
That detail matters for how you build it. Many hosted brokers, including ConnectMQ, do not run an outbound bridge themselves. Instead, you run the bridge at the edge: a Mosquitto instance in the plant, or a Node-RED flow on a gateway, connects out to the cloud broker as a client. This is also the more firewall-friendly direction, since the site only needs outbound access on port 8883.
Typical reasons to bridge:
- Local autonomy. PLC adapters, HMIs and controllers keep talking to a broker on the plant network even if the internet link drops.
- Selective export. Only aggregated or approved topics leave the site, not every raw signal.
- Fewer cloud connections. Hundreds of local devices share one upstream connection, which keeps you inside connection quotas.
- Namespace mapping. Local topics like
line4/press/tempbecome globally unique cloud topics likeacme/izmir/line4/press/temp.
Bridging Topologies
| Topology | Description | Good for | Watch out for |
|---|---|---|---|
| Edge to cloud (out) | Local broker pushes selected topics up | Telemetry, dashboards, historians | Buffering during outages |
| Cloud to edge (in) | Cloud commands flow down to the site | Setpoints, configuration, OTA triggers | Authorizing who may command |
| Bidirectional | Both directions on separate topic trees | Full remote operation | Message loops |
| Hub and spoke | Many sites bridge to one central broker | Multi-site Unified Namespace | Topic collisions between sites |
The hub-and-spoke pattern is the backbone of many Unified Namespace and Sparkplug B designs: each site owns its local broker and contributes one branch to the enterprise topic tree in the cloud.
Option 1: Mosquitto Bridge to a Cloud Broker
Eclipse Mosquitto has a built-in bridge feature configured in mosquitto.conf. The example below runs a local broker for plant devices on port 1883 and bridges to a ConnectMQ broker over TLS on 8883 using the credentials generated in the portal.
# /etc/mosquitto/conf.d/bridge-connectmq.conf
# --- Local listener for devices on the plant network ---
listener 1883
# Tighten with password_file in production
allow_anonymous true
# --- Bridge to ConnectMQ (cloud) ---
connection connectmq-cloud
address broker.connectmq.com:8883
bridge_protocol_version mqttv311
bridge_capath /etc/ssl/certs
bridge_insecure false
remote_clientid YOUR_CLIENT_ID
remote_username YOUR_USERNAME
remote_password YOUR_PASSWORD
# Keep the remote session so QoS 1 messages survive short reconnects
cleansession false
keepalive_interval 60
restart_timeout 5 60
# The remote broker is not Mosquitto: do not use the private bridge flag
try_private false
notifications false
# Local buffering while the uplink is down
max_queued_messages 10000
# topic <pattern> <direction> <qos> <local-prefix> <remote-prefix>
# Local plant/line4/... -> cloud acme/izmir/line4/...
topic # out 1 plant/ acme/izmir/
# Cloud acme/izmir/cmd/... -> local cmd/...
topic # in 1 cmd/ acme/izmir/cmd/
How the topic lines work: Mosquitto takes the pattern (#), prepends the local prefix to build the local subscription (plant/#), and on forwarding swaps the local prefix for the remote prefix. A local message on plant/line4/press/temp appears in the cloud as acme/izmir/line4/press/temp. The in line does the reverse for commands.
Notes on the important settings:
remote_clientidmust be the client ID issued with your credentials. The broker binds client IDs to credentials, so a random ID will be rejected.try_private false. Mosquitto's private bridge flag is a Mosquitto-to-Mosquitto extension; other brokers may refuse it.notifications false. Otherwise Mosquitto publishes bridge state messages to$SYS/broker/connection/...topics, which a non-Mosquitto remote may not accept.bridge_capath. Points at the system CA store. The broker presents a Let's Encrypt certificate, which is in that store on standard Linux distributions.max_queued_messages. Bounds how many messages the local broker buffers while the uplink is down. Size it to your outage tolerance and disk.
Restart Mosquitto and watch its log for Connecting bridge connectmq-cloud followed by a successful connection. If it fails, the log line with the CONNACK code tells you whether it is a credentials or TLS issue.
Test the bridge end to end
# On a laptop: watch the cloud side
mosquitto_sub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
-u YOUR_USERNAME -P YOUR_PASSWORD -i YOUR_OTHER_CLIENT_ID \
-t "acme/izmir/#" -v
# On the plant network: publish to the local broker
mosquitto_pub -h 192.168.10.5 -p 1883 -i press-sim-01 \
-t "plant/line4/press/temp" -m "78.2" -q 1
You should see acme/izmir/line4/press/temp 78.2 in the cloud subscriber. Note that the laptop needs its own credential set; two connections cannot share one client ID. For a credential-free trial, point the bridge at the public MQTT test broker on port 1883, drop the username and password lines, use a unique remote_clientid, and use a remote prefix like connectmq/demo/b7e2/ (public data is visible to everyone).
Option 2: Node-RED as a Bridge
If the site already runs Node-RED, you may not need a second broker process at all. A flow with two MQTT config nodes acts as a bridge and gives you a place to filter, rename and transform messages.
- Add an
mqtt innode using a broker config for the local broker (for example192.168.10.5:1883) subscribed toplant/#at QoS 1. - Add a
functionnode to remap topics and drop anything you do not want to export. - Add an
mqtt outnode using a second broker config: serverbroker.connectmq.com, port 8883, "Use TLS" enabled, with your portal username, password and client ID.
// Function node: remap local topics to the cloud namespace
const LOCAL_PREFIX = "plant/";
const REMOTE_PREFIX = "acme/izmir/";
if (!msg.topic.startsWith(LOCAL_PREFIX)) {
return null; // ignore unexpected topics
}
// Example filter: do not export raw debug signals
if (msg.topic.includes("/debug/")) {
return null;
}
msg.topic = REMOTE_PREFIX + msg.topic.slice(LOCAL_PREFIX.length);
msg.qos = 1;
return msg;
For commands coming down, add a mirror path: mqtt in on the cloud config subscribed to acme/izmir/cmd/#, a function node that rewrites the prefix to cmd/, and mqtt out to the local broker. The Node-RED MQTT tutorial covers config nodes and TLS settings in detail, and the official Node-RED documentation lists every MQTT node option.
The trade-off: Node-RED does not buffer to disk the way a broker can. If the uplink is down, messages flowing through the flow are lost unless you add your own queueing. Mosquitto is the better choice when you need store-and-forward; Node-RED wins when you need logic.
Preventing Message Loops
Bidirectional bridges can create loops: a message goes up, matches the downward rule, comes back, goes up again. Rules that keep you safe:
- Use disjoint topic trees per direction, as above (
plant/goes out,cmd/comes in). - Never bridge
#in both directions with the same prefixes. - In MQTT 5 setups, the No Local subscription option stops a client from receiving its own publishes, which helps when the bridge subscribes and publishes on the same connection.
- Test with a single message and watch both sides before enabling production traffic.
Troubleshooting Checklist
| Symptom | Likely cause | Fix |
|---|---|---|
| CONNACK not authorized | Wrong credentials or client ID | Copy all three values from the portal |
| TLS error on connect | CA store missing or wrong path | Install ca-certificates, check bridge_capath |
| Bridge connects then drops | Duplicate client ID used elsewhere | Give every client its own credential set |
| Topics appear without prefix | Topic line prefixes swapped | Order is local prefix, then remote prefix |
| Data gaps after outage | Queue too small or QoS 0 | Use QoS 1 and raise max_queued_messages |
| Messages echo endlessly | Overlapping in/out rules | Separate trees per direction |
Choosing a Cloud Endpoint for Your Bridges
The cloud side should be boring: always on, TLS by default and able to accept one upstream connection per site plus your dashboards and services. A managed MQTT broker removes the patching and certificate work, and the cloud MQTT broker guide walks through hosting trade-offs. If you are new to these building blocks, the beginner MQTT tutorial and the publish/subscribe model are good companions to this article.
Bridge Your Sites to ConnectMQ
Create a free Serverless broker at app.connectmq.com, no credit card required, then paste the generated username, password and client ID into your Mosquitto bridge or Node-RED config node. ConnectMQ's live topic explorer shows bridged topics arriving in real time, so you can confirm the mapping before connecting more sites.
Frequently Asked Questions
Does ConnectMQ have a built-in bridge?
No. You bridge into it by running Mosquitto, Node-RED or another MQTT client at the edge that connects to the broker as a normal client over TLS.
Can I bridge MQTT 5 features like user properties?
Set bridge_protocol_version mqttv50 in Mosquitto to bridge with MQTT 5. Check that both brokers support MQTT 5 and test that the properties you rely on are forwarded.
How many connections does a bridge use?
A Mosquitto bridge uses one connection to the remote broker regardless of how many local devices publish through it. A Node-RED bridge uses one connection per broker config node.
What happens to data when the internet link goes down?
A Mosquitto bridge queues messages locally up to max_queued_messages and forwards them when the link returns. Plain Node-RED flows do not buffer unless you add it.



