The Broker Choice Nobody Wants to Think About
You’ve got a dozen IoT devices around your home. Your Home Assistant box is polling them. Your Frigate camera is dumping events. Your Tasmota switches are reporting state changes. And somewhere in that chaos, you need to pick an MQTT broker—the message bus that everything talks to.
The choice sounds boring. It’s not. Pick the wrong one, and you’re either throwing away CPU cycles on unnecessary bloat or scrambling to add features you should’ve planned for. Pick right, and your home stack hums along invisible.
Let me cut through it: Mosquitto is the default choice for 99% of home labs. EMQX is there if you’ve outgrown Mosquitto or you’re planning to outgrow it before you build it. This post is about knowing which one you actually need, not which one has the fancier name.
Mosquitto: The Lightweight Standard
Mosquitto is what you’re already running. It’s in every Docker repo, it’s one apt install away on Linux, and it just works. It’s been the home lab broker of choice since 2010.
Here’s what you get:
- Tiny footprint — 10-30 MB RAM under normal load. This thing can run on a Raspberry Pi Zero.
- Single binary — No clustering nonsense, no distributed consensus to debug at 2 AM.
- MQTT 3.1.1 and 5.0 support — Full spec compliance. Your clients work.
- Basic auth and ACLs — Username/password and topic-based access control via a flat file. Not fancy, but it works.
- Persistence — Messages survive a restart if you configure it.
- Bridges — Chain multiple Mosquitto brokers together. Handy if you’re running one on the main house and another in the garage.
The trade-off? Mosquitto is single-node only. If your broker dies, everything stops until you restart it. For a home lab, that’s fine—you can survive an hour of downtime. Mosquitto also doesn’t scale horizontally. If you somehow end up with 10,000 clients (you won’t), Mosquitto maxes out around 1,000-2,000 depending on your hardware.
Here’s a typical Mosquitto Compose setup:
services: mosquitto: image: eclipse-mosquitto:latest ports: - "1883:1883" - "8883:8883" - "9001:9001" volumes: - ./config/mosquitto.conf:/mosquitto/config/mosquitto.conf - ./data/mosquitto:/mosquitto/data environment: - TZ=UTC restart: unless-stoppedAnd a basic config:
listener 1883protocol mqtt
listener 8883protocol mqttcafile /mosquitto/certs/ca.crtcertfile /mosquitto/certs/server.crtkeyfile /mosquitto/certs/server.key
listener 9001protocol websockets
persistence truepersistence_location /mosquitto/data/That’s it. Plug in some TLS certs, point your clients at your-homelab.local:1883, and you’re done. The whole thing runs on a 10-year-old laptop.
EMQX: The Feature-Laden Overachiever
EMQX is what Mosquitto wants to be when it grows up and gets a job at an IoT unicorn. It’s an Erlang-based broker built for scale, clustering, enterprise auth, and features Mosquitto doesn’t even know exist.
What you gain:
- Clustering — Spin up multiple EMQX nodes, cluster them, lose one without dropping connections. Your clients auto-reconnect to another node.
- Massive scale — EMQX is tested at millions of concurrent connections. It’ll handle your home lab’s 50-200 clients like they’re not even there.
- Advanced auth — HTTP hooks, JWT, SQL backends, LDAP. Plug in your authentication system instead of a flat file.
- Built-in monitoring — Real-time dashboard, Prometheus metrics, webhooks for events.
- Message routing — Rule engine lets you transform and route messages without touching your client code.
- Replication — Data replication across cluster nodes. Broker dies, your session state survives.
- Plugins — Extend via Erlang if you’re masochistic.
- MQTT 5.0 — Full support, including shared subscriptions and request/response patterns.
The downside? EMQX is 500+ MB on disk, runs 100+ MB RAM even idle, and requires actual operational overhead. Clustering means you need to think about networking, consensus, failover. If something breaks, you’re Googling Erlang error messages at midnight.
Here’s EMQX in Compose:
services: emqx: image: emqx/emqx:latest ports: - "1883:1883" - "8883:8883" - "9001:9001" - "18083:18083" environment: - EMQX_NODE_NAME=emqx@emqx - EMQX_CLUSTER__DISCOVERY_STRATEGY=static - EMQX_AUTH__USER=admin - EMQX_AUTH__PASSWORD=your-password-here volumes: - ./data/emqx:/opt/emqx/data restart: unless-stopped healthcheck: test: ["CMD", "/opt/emqx/bin/emqx", "ctl", "status"] interval: 30s timeout: 10s retries: 3Three nodes clustered together:
services: emqx1: image: emqx/emqx:latest environment: - EMQX_CLUSTER__DISCOVERY_STRATEGY=static ports: - "1883:1883" volumes: - ./data/emqx1:/opt/emqx/data networks: - mqtt
emqx2: image: emqx/emqx:latest environment: - EMQX_CLUSTER__DISCOVERY_STRATEGY=static ports: - "1883:1883" volumes: - ./data/emqx2:/opt/emqx/data networks: - mqtt
emqx3: image: emqx/emqx:latest environment: - EMQX_CLUSTER__DISCOVERY_STRATEGY=static ports: - "1883:1883" volumes: - ./data/emqx3:/opt/emqx/data networks: - mqtt
networks: mqtt: driver: bridgeNow you need to manage three stateful services, worry about clock skew, debug Erlang clustering quirks, and remember to upgrade all three at once. Fun!
Side-by-Side Comparison
| Feature | Mosquitto | EMQX |
|---|---|---|
| Memory (idle) | 10-30 MB | 100-150 MB |
| Single-node setup | 5 minutes | 10 minutes |
| Clustering | No | Yes (3+ nodes) |
| Max concurrent clients | ~2,000 | Millions |
| TLS/SSL | Yes | Yes |
| Authentication | Password file, basic ACLs | HTTP hooks, JWT, SQL, LDAP, file, HTTP |
| Persistence | Yes | Yes |
| WebSockets | Yes | Yes |
| Message routing | Basic bridging | Rule engine (transform, filter, route) |
| Monitoring | None (use external tools) | Built-in dashboard, Prometheus |
| Operational complexity | Minimal | Moderate to high at scale |
| Learning curve | Hours | Days to weeks |
| Perfect for | Home labs, small offices | Multi-site deployments, high availability |
When to Pick Mosquitto
Just use Mosquitto if:
- Your home lab has fewer than 500 devices (you’ll never hit this).
- You tolerate 30 minutes of downtime once every few years when you restart it.
- You don’t need dynamic authentication or complex message routing.
- You want something you can debug at 3 AM without pulling your hair out.
- You’re running this on a Raspberry Pi or low-power hardware.
- You’re bridging two Mosquitto instances in different locations and that’s enough.
This covers 98% of home labs. Seriously. If you stopped reading here and picked Mosquitto, you’d be making the right call.
When EMQX Makes Sense
Pick EMQX if:
- You’re deploying MQTT across multiple physical locations and need failover without downtime.
- You need to authenticate clients against an existing auth system (LDAP, JWT, HTTP backend).
- You’re pre-planning for 10,000+ devices (enterprise IoT deployments).
- You want real-time monitoring and alerting without plugging in Prometheus.
- You need message transformation at the broker level (rule engine).
- You’re doing something so complex that Mosquitto’s limitations would force ugly client-side hacks.
- You run a managed Kubernetes cluster and want an operator to handle scaling.
Also: EMQX offers a cloud version if you want zero operational overhead. That’s not home lab territory—that’s “I’d rather pay money than debug Erlang” territory.
The Honest Take
You’re probably overthinking this. Start with Mosquitto. Run it in a container, point your devices at it, and move on. If it works for six months (it will), stop. Don’t add complexity preemptively.
The only reason to pick EMQX from day one is if you’re building something that’s explicitly multi-site or high-availability from the ground up. That’s rare in home labs. Most of us just want a message bus that doesn’t crash and let’s us avoid polling.
Here’s the real decision tree:
- Single home lab, <500 devices → Mosquitto. Done.
- Two locations that need to sync → Mosquitto with bridges.
- One location but you need HA clustering → EMQX, 3+ nodes.
- Complex auth or message routing → EMQX’s rule engine or HTTP hooks.
- Millions of connections → EMQX or HiveMQ (another option, not covered here).
Anything else is like hiring a forklift to move a couch. Technically it works, but your neighbors will have questions.
Migration Path (If You Change Your Mind)
Built Mosquitto and now you’re hitting limits? The migration is straightforward:
- Spin up EMQX alongside Mosquitto.
- Point new devices at EMQX.
- Move old devices one by one (subscribe to EMQX in Home Assistant, point the device, restart).
- Once all clients are on EMQX, kill Mosquitto.
MQTT clients don’t care which broker they’re talking to—they speak the same language. Use that to your advantage.
Final Word
Mosquitto is battle-tested, lightweight, and maintainable. EMQX is powerful, over-engineered, and worth the complexity if you actually need it. Pick Mosquitto first. Upgrade to EMQX later if you hit walls. That’s not settling—that’s respecting your own time.
Your 2 AM self will thank you for not running three clustered Erlang services when one lightweight C daemon would’ve done the job.