Learn NATS - Integration & Best Practices
Series/Learn NATS/Episode 15
Episode 15 of 23

Learn NATS - Integration & Best Practices

This episode covers NATS integration as an MQTT broker for IoT devices via the mqtt configuration block, then summarizes best practices: subject naming conventions, backpressure, timeouts, and the correct event-driven patterns for microservices.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Episode 14 built the scale. Episode 15 connects NATS to the outside world and tidies up your practices: you'll learn to use NATS as an MQTT broker for IoT devices, then review the best practices that keep an architecture healthy — subject naming, backpressure, timeouts, and the correct event-driven patterns.

This is a bridge episode: most of its content is the habits you'll carry all the way to episode 22.

MQTT Bridge: NATS as an IoT Broker

The MQTT Concept in NATS

MQTT is a lightweight protocol for IoT devices. Since version 2.10, NATS can act as an MQTT broker directly — MQTT-speaking devices connect to NATS without a separate gateway.

Enable MQTT in NATS
mqtt {
  listen: "0.0.0.0:1883"
  no_auth_user: mqtt-user
  ack_wait: 30s
  max_ack_pending: 100
}

The mqtt block enables an MQTT listener on port 1883. IoT devices use the regular MQTT protocol, and NATS maps MQTT topics to NATS subjects transparently.

Mapping MQTT Topics to NATS Subjects

MQTT has topics, NATS has subjects. NATS bridges the two:

Subscribe to an MQTT topic from the NATS CLI
nats sub 'sensors.>'
mosquitto_pub -h localhost -t "sensors/temp" -m "24.5"

nats sub 'sensors.>' listens on the sensors.> subject, while the MQTT device publishes to the sensors/temp topic, which is automatically mapped to the sensors.temp subject. One server serves IoT devices and microservices at the same time.

The Power of MQTT Integration

Because MQTT maps to NATS subjects, all NATS features apply to IoT data right away: JetStream streams for recording sensor data, work queues for processing, and request-reply for device control. No additional systems needed.

Best Practices: Subject Naming

Consistent Conventions

Naming consistency determines how readable your system is:

  • Use dots as hierarchy separators: orders.created.eu.
  • Past tense for events, present tense for requests.
  • Avoid wildcards when publishing; save them for subscriptions.
  • Document your subject schema early in the project.
A consistent subject schema
domain.entity.action
orders.created, orders.cancelled
payments.charged, payments.refunded
sensors.temp.room-1

The domain.entity.action schema makes every subject readable at a glance. You'll be grateful for this convention when writing permissions or debugging in episode 19.

Best Practices: Backpressure

Keeping Publishers Under Control

Backpressure prevents consumers from being overwhelmed. In Core NATS, an unlimited publisher can flood a slow subscriber. The solutions:

  • Use queue groups to spread the load between workers.
  • Use JetStream pull consumers so workers fetch messages at their own capacity.
  • Monitor consumer pending counts regularly.
Check consumer pending counts
nats consumer report ORDERS

nats consumer report ORDERS shows the number of pending messages per consumer. If the number keeps rising, that's a signal backpressure is needed — add workers or slow the publisher down.

Best Practices: Timeouts

Wait-Time Discipline

Timeouts keep your system responsive in the face of failures:

Request with a timeout
nats request auth.login '{"user":"arman"}' --timeout=2s

The --timeout=2s flag forces the request to stop waiting after 2 seconds. Chain rule: a caller's timeout must be smaller than the handler's timeout, so errors don't pile up in layers. Publishing to a stream also needs a bounded ack to know whether the message was really received.

Best Practices: Event-Driven Patterns

The Right Microservices Architecture

Several proven patterns for microservices:

  • Event publishing: a service publishes facts that happened, without knowing who's listening.
  • Request-reply for operations that need an immediate answer.
  • Job queues for tasks that can be processed asynchronously.
  • Streaming pipelines for continuous data flows.
Event-driven patterns with NATS
orders service --> publish orders.created --> stream ORDERS
                                               ├── notification service
                                               ├── inventory service
                                               └── analytics worker

The orders service -> publish orders.created flow shows one event consumed by many services without direct coupling. This is the essence of a decoupled architecture — and the theme we'll refine in episode 21.

Tip

Start with one pattern per service: don't mix request-reply and streaming in a single flow without a clear reason. Simplicity is the greatest asset of a messaging architecture.

Conclusion

Episode 15 connected NATS to the world of IoT devices via the MQTT bridge and tidied up engineering practices: consistent subject naming conventions, backpressure to protect consumers, disciplined timeouts, and the correct event-driven patterns for microservices.

Key takeaways:

  • NATS can act as an MQTT broker with just an mqtt block in the configuration.
  • MQTT topics map to NATS subjects; all JetStream features apply to IoT data.
  • Use the domain-entity-action pattern for subject naming.
  • Pull consumers and queue groups are your main weapons against backpressure.
  • Timeouts are mandatory on requests; smaller at the caller than the handler.
  • One event is published once and consumed by many services without coupling.

In episode 16 next, we'll discuss JetStream performance — high-throughput publishing in version 2.14+, batching for bulk publishing, server-side message scheduling, scaling with replication and partition across subjects, storage tuning, and benchmarks toward millions of messages per second. NATS starts showing its teeth.

Learn NATS - Integration & Best Practices | Learn NATS