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.