MQTT Fundamentals

MQTT vs NATS: Choosing a Messaging System for IoT

MQTT and NATS are both lightweight publish/subscribe systems, but they target different clients. This comparison covers device support, delivery guarantees, persistence and ecosystem so you can place each one correctly.

Diagram of microcontrollers connected to an MQTT broker beside backend services on a NATS cluster, comparing MQTT vs NATS
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

MQTT vs NATS is a comparison that comes up when a team likes the simplicity of NATS for microservices and wonders whether it can also serve its devices. Both are lightweight publish/subscribe systems with wildcard subscriptions and low latency, yet they were shaped by very different clients. This guide compares device support, delivery guarantees, persistence and ecosystem, and explains where a managed MQTT broker fits next to NATS.

Two Lightweight Pub/Sub Systems

MQTT is an open OASIS standard protocol. Any compliant client can talk to any compliant broker, and there are many implementations of both. It was built for telemetry from constrained devices over unreliable networks, which is why it has features such as Last Will, retained messages and persistent sessions.

NATS is an open-source messaging system and protocol from the CNCF ecosystem, with one primary server implementation. It was built for cloud-native service-to-service communication: fast request/reply, fan-out and load-balanced work distribution inside and across data centers. Core NATS is deliberately fire-and-forget; JetStream, built into the NATS server, adds persistence, replay and stronger delivery guarantees.

Both are good at what they were designed for. The question is which clients you are connecting.

MQTT vs NATS at a Glance

Aspect MQTT NATS
Nature OASIS standard protocol, many brokers Open-source system, one primary server
Addressing Topics with / levels, wildcards + and # Subjects with . tokens, wildcards * and >
Delivery (core) QoS 0, 1, 2 At most once in core NATS
Persistence Retained last value, session queues JetStream streams with replay and retention
Work distribution Shared subscriptions (MQTT 5) Queue groups
Request/reply Response topic and correlation data (MQTT 5) Built in with inbox subjects
Presence Keep alive and Last Will Connection events via system account, no Last Will
Last-known value Retained messages JetStream last-per-subject or KV store
Device libraries Mature options for ESP32, Arduino, embedded C, RTOS Focus on server languages; few microcontroller options
Browser access MQTT over WebSocket NATS over WebSocket
Industrial ecosystem Sparkplug B, Unified Namespace, PLC and gateway support Limited
Typical home Devices, gateways, HMIs, dashboards Microservices, edge-to-cloud backends, control planes

Device Support Is the Deciding Factor

For IoT, the most practical difference is client availability. MQTT clients exist for practically every platform a device engineer touches: ESP32 and Arduino libraries such as PubSubClient, embedded C libraries for RTOS targets, cellular modules with MQTT in the modem firmware, PLCs and industrial gateways with MQTT built in, and SCADA and historian software that speaks Sparkplug B. Off-the-shelf sensors and gateways often ship with MQTT as a configuration option.

NATS clients are excellent for Go, Rust, Java, .NET, JavaScript, Python and C on Linux-class hardware. A Raspberry Pi or an industrial PC can run them comfortably. On microcontrollers and in vendor firmware, NATS support is rare. If you need a commercial device to send data without writing firmware, it will almost certainly speak MQTT, not NATS.

Delivery Guarantees and Persistence

MQTT bakes delivery guarantees into every message. A device can publish an alarm at QoS 1 and a high-rate vibration reading at QoS 0 on the same connection. Persistent sessions hold QoS 1 and 2 messages for a subscriber that disconnects, and retained messages hold the last value per topic so a dashboard that opens later sees current state immediately. For details see MQTT QoS levels explained and MQTT retained messages.

Core NATS delivers to whoever is connected at that moment and nothing more. That is fast and simple, and it is the right model for many service calls. When you need durability, JetStream stores messages in streams with retention policies, lets consumers acknowledge and replay, and can deduplicate by message ID. JetStream is more capable than MQTT sessions for history and replay, but it is a separate set of concepts (streams, consumers, acknowledgment policies) that someone has to design and operate.

Presence and Device State

IoT systems constantly need to answer "is this device online, and what was its last reading?" MQTT answers both natively. A device sets a Last Will such as offline on site1/pump7/status with the retain flag, publishes online after connecting, and the broker publishes the will if the connection drops ungracefully. See the MQTT Last Will and Testament guide for the full pattern.

In NATS you would typically build presence with heartbeats from each device, or watch connection events from the server's system account, and store last values in a JetStream key-value bucket. It works, but you are assembling it rather than configuring it.

Subjects vs Topics

The naming models are similar enough to translate. An MQTT topic factory1/line2/cnc1/temperature maps naturally to a NATS subject factory1.line2.cnc1.temperature. MQTT + matches one level like NATS *, and MQTT # matches the remainder like NATS >. The NATS server even offers an MQTT interface that maps topics to subjects in this way and can accept MQTT 3.1.1 clients, which is useful when NATS is already the backbone. It does not support MQTT 5 features, so check the NATS documentation against the features your devices rely on.

A Practical Hybrid Architecture

Plenty of teams use both, each at the layer it suits:

  1. Devices, PLC gateways and HMIs connect to an MQTT broker over TLS.
  2. A bridge service subscribes to device topics and republishes to NATS subjects for backend microservices.
  3. Services use NATS request/reply and queue groups internally, and JetStream where they need durable streams.
  4. Commands go back through the bridge and are published to the device's MQTT command topic.

A minimal one-way bridge in Go looks like this, using the Eclipse Paho Go client and the official NATS client.

package main

import (
	"crypto/tls"
	"log"
	"strings"

	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/nats-io/nats.go"
)

func main() {
	nc, err := nats.Connect(nats.DefaultURL)
	if err != nil {
		log.Fatal(err)
	}
	defer nc.Drain()

	opts := mqtt.NewClientOptions().
		AddBroker("tls://broker.connectmq.com:8883").
		SetClientID("YOUR_CLIENT_ID").
		SetUsername("YOUR_USERNAME").
		SetPassword("YOUR_PASSWORD").
		SetTLSConfig(&tls.Config{MinVersion: tls.VersionTLS12}).
		SetAutoReconnect(true)

	opts.SetOnConnectHandler(func(c mqtt.Client) {
		// Subscribe in the connect handler so it is restored after reconnects
		c.Subscribe("factory1/+/+/telemetry", 1, func(_ mqtt.Client, m mqtt.Message) {
			subject := strings.ReplaceAll(m.Topic(), "/", ".")
			if err := nc.Publish(subject, m.Payload()); err != nil {
				log.Printf("nats publish failed: %v", err)
			}
		})
	})

	client := mqtt.NewClient(opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		log.Fatal(token.Error())
	}
	log.Println("bridging MQTT to NATS")
	select {}
}

The paho Go client uses MQTT 3.1.1, which ConnectMQ accepts alongside MQTT 5. To try it without credentials, use tcp://broker.connectmq.com:1883, any unique client ID and a topic prefix such as connectmq/demo/<random-id>/ on the public MQTT test broker. Watch out for characters that are legal in MQTT topics but special in NATS subjects, such as . or spaces, and sanitize them in the bridge.

When to Choose Which

Choose MQTT when your clients are devices, gateways, PLCs or third-party hardware, when connectivity is unreliable, or when you need presence, retained state and industrial conventions such as Sparkplug B and a Unified Namespace.

Choose NATS when your clients are services you write, running on reliable networks, and you want fast request/reply, queue groups and optional JetStream persistence with minimal infrastructure.

Choose both when you have a device fleet and a microservice backend that already standardizes on NATS.

For the device layer, a managed MQTT broker removes the work of running and securing an internet-facing service. ConnectMQ offers MQTT 3.1.1 and 5.0, TLS, shared subscriptions on the paid Serverless plan, per-plan quotas and multi-tenant isolation, without a NATS bridge built in, so the bridge stays your own small service as shown. If you are comparing other backends too, see MQTT vs Kafka, and for fundamentals the MQTT tutorial.

Get Started with ConnectMQ

Give your devices a standard, well-supported MQTT endpoint and keep NATS for your services. Create a free Serverless broker at app.connectmq.com, no credit card required, connect a device and your bridge, and watch both sides in the live topic explorer.

Frequently Asked Questions

Is NATS faster than MQTT?

Both are low-latency, and real-world speed depends on the server, network and delivery settings more than the protocol. Choose based on clients and features rather than raw speed.

Can IoT devices connect to NATS directly?

Linux-class devices can use NATS clients. Microcontrollers and commercial sensors rarely support NATS, which is why MQTT dominates at the device layer.

Does NATS support MQTT clients?

The NATS server provides an MQTT 3.1.1 interface backed by JetStream. It does not cover MQTT 5 features, so a dedicated MQTT broker is usually a better fit for large mixed fleets.

What is the NATS equivalent of an MQTT retained message?

The closest equivalents are a JetStream stream configured to keep the last message per subject, or a JetStream key-value bucket. Both must be set up explicitly.

Related articles

Why Your MQTT Client Keeps Disconnecting (and How to Fix It)

Reconnect loops are one of the most common MQTT problems. Learn the five usual causes, from duplicate client IDs to keep alive timeouts and oversized packets, and follow a diagnosis flow that pinpoints yours.

8 min read

Who Invented MQTT? The History from Oil Pipelines to IoT

MQTT was invented in 1999 by Andy Stanford-Clark of IBM and Arlen Nipper of Arcom to monitor oil pipelines over satellite. Follow its path to open source, OASIS, ISO and today's managed cloud brokers.

7 min read

MQTT Maximum Message Size: Limits and Large Payload Strategies

MQTT can technically carry a 256 MB packet, but brokers, client libraries and devices impose far lower limits. Learn where the real limits are, what happens when you exceed them, and how to send large payloads.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.