We build a real-time platform that processes live audio streams from contact centers and routes events between multiple microservices with very low latency. When choosing a messaging layer, the usual options came up Kafka, RabbitMQ, Redis Pub/Sub. We went with NATS.
NATS is a lightweight messaging system from CNCF ecosystem. It's a single binary, requires almost no configuration, and supports multiple messaging patterns out of the box.
What made NATS a good fit for our system was how naturally it mapped to the messaging problems we had.
We needed:
Some messages to go to exactly one consumer (load-balanced processing)
Some messages to go to every consumer (coordination broadcasts)
Some messages to go to a specific consumer responsible for an entity
Some messages to support request–reply between services (across Java and Python)
With systems like Apache Kafka or RabbitMQ, these patterns usually involve different topic setups, consumer groups, or extra infrastructure.
With NATS, most of this comes down to how you structure subjects and use queue groups.
In this talk I'll walk through:
How Core NATS pub/sub, queue groups, and request–reply work
How we designed our subject namespace for different delivery patterns on the same cluster
Dynamic subscriptions based on entity lifecycle
Why we chose Core NATS over JetStream for ephemeral real-time data
Production lessons like slow consumers, orphaned subscriptions, and cross-language request–reply
No prior NATS experience is required, though familiarity with messaging systems will help.
Learn how to use queue groups, fan-out, request–reply, and dynamic subscriptions on one NATS cluster
Subject namespace design patterns for per-entity real-time systems
When Core NATS is enough, and when you might actually need JetStream