NATS is a lightweight, high-performance messaging system designed for cloud-native and microservice communication. The core server is a small single binary that does publish/subscribe and request/reply with very low latency. An optional layer called JetStream adds persistence, replay, and at-least-once delivery, so one system can cover both ephemeral messaging and durable streaming.

Subjects and core pub/sub

NATS routes on subjects - dot-separated names like orders.eu.created - with wildcards (orders.*.created, orders.>) for flexible subscriptions. Core NATS is fire-and-forget: if no subscriber is listening, the message is gone. That makes it extremely fast and simple for service-to-service calls, live telemetry, and request/reply, where a missed message doesn't matter or the caller retries.

import asyncio, nats
async def main():
    nc = await nats.connect("nats://broker:4222")
    await nc.subscribe("orders.*.created", cb=handle)
    await nc.publish("orders.eu.created", b'{"id": 42}')
    # request/reply
    reply = await nc.request("inventory.check", b"sku-7", timeout=1)
asyncio.run(main())

JetStream: persistence and streaming

Core NATS doesn't store messages; JetStream does. It captures messages on configured subjects into streams with retention limits (by age, size, or count), and consumers read with acknowledgements and replay - closer to Kafka's model. This lets you start with simple pub/sub and add durability only where you need it, instead of running a separate streaming platform. JetStream also supports key-value and object stores built on the same primitives.

Why teams choose it

  • Operational simplicity - one small binary, easy clustering, low resource footprint; popular in Kubernetes and edge/IoT.
  • Latency - built for fast request/reply and high message rates with minimal overhead.
  • One system, two modes - ephemeral messaging plus optional durable streams.

NATS vs Kafka vs RabbitMQ

NATS core is lighter and faster to operate than either, but core delivery is fire-and-forget; durability requires JetStream. Kafka remains the choice for very high sustained throughput, long retention, and a large stream-processing ecosystem. RabbitMQ offers richer built-in routing semantics (exchanges, dead-letter handling). NATS fits best when you want a simple, fast messaging fabric for microservices - and the option to turn on persistence selectively - without operating a heavier platform.

Where it fits

  • Service-to-service messaging and request/reply in microservice and Kubernetes environments.
  • Edge and IoT, where a tiny footprint matters.
  • Workloads that mix transient signaling with a few durable streams via JetStream.