One Broker or Many? Structuring Mosquitto for Multiple Use Cases

When one Mosquitto broker with multiple listeners is the right architecture, and when running genuinely separate broker instances makes more sense.

Once an MQTT deployment grows past a single use case — say, existing TCP clients alongside new TLS-only clients, or maybe WebSockets too — a natural question comes up: one broker configured to handle all of it, or several independent broker instances? Mosquitto supports both, and the right answer depends less on technology and more on organizational and operational boundaries.

One Mosquitto, multiple listeners

Mosquitto is explicitly built to support this pattern. A single broker process can expose several listeners simultaneously:

  • Listener 1: the existing TCP listener with username/password auth (e.g. port 1883)
  • Listener 2: a new TLS listener for MQTT over TLS (e.g. port 8883)
  • Optionally: WebSocket listeners too, TLS and non-TLS as needed

Why this is often the right default:

  • Simpler operations. One service to monitor, log, back up, and restart.
  • Lower resource usage. One process, shared persistence, one set of queues.
  • Shared topics. Clients on TLS and non-TLS listeners can exchange messages without extra bridging.
  • A consistent ACL model. One topic tree, one mental model for permissions — nothing to keep in sync across brokers.

The key configuration lever is per_listener_settings true, which lets each listener have its own ACLs, password files, and auth behavior. This makes a staged rollout straightforward: start everyone on username/password over TLS, and later tighten the TLS listener to require client certificates — without touching the non-TLS listener’s configuration at all.

A conceptual configuration sketch:

# Global
per_listener_settings true
...

# Listener 1: existing non-TLS
listener 1883
password_file /etc/mosquitto/passwd-internal
acl_file /etc/mosquitto/acl-internal
...

# Listener 2: new TLS listener
listener 8883
password_file /etc/mosquitto/passwd-tls
acl_file /etc/mosquitto/acl-tls

cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
...

When two separate instances actually make sense

Running genuinely separate brokers is the right call when any of the following apply:

Different trust boundaries or tenants. One broker for the internal network, another for external partners or cloud integration — especially when policy explicitly states that different environments must not share the same message bus.

Very different lifecycle and ownership. If one broker is owned by a system management team and another by a product team, with different deployment schedules, upgrade cadences, and possibly even different Mosquitto versions, forcing them onto shared infrastructure creates coordination overhead that outweighs the resource savings.

Hard isolation and resource control. If heavy load from a new use case could degrade traffic that’s actually critical, separate processes let you cap resource usage independently instead of hoping one workload doesn’t starve the other.

Different network topologies. One broker reachable only from an internal VLAN, another sitting in a DMZ behind its own firewall path or reverse proxy — even on the same host, separate instances can bind to different interfaces to enforce this cleanly.

Migration or blue-green upgrades. Standing up a new instance with updated configuration, migrating clients over gradually, and retiring the old instance is a much cleaner story with genuinely separate brokers than with listener changes on a shared one.

They’re not mutually exclusive

If you do go the separate-instances route, that doesn’t mean the two brokers have to be islands — Mosquitto bridging lets you connect them so topics can still flow between the two where it’s actually needed, giving you isolation where it matters and connectivity where it doesn’t.

The bottom line

Default to one broker with multiple listeners — it’s simpler to run and easier to reason about. Reach for separate instances when the boundary between use cases is organizational or security-driven rather than purely technical; that’s the signal that a shared process is the wrong abstraction, not a resource optimization you’re leaving on the table.