This episode breaks down how NATS works behind the scenes: subjects and wildcards for routing, the communication patterns of publish/subscribe, request-reply, and queue groups, as well as the role of JetStream as the persistence layer, complete with the components of the NATS ecosystem.

Episode 1 gave you the reasons why NATS exists. Episode 2 goes one level deeper: how NATS works behind the scenes. This is the architectural foundation — after this episode, terms like subject, wildcard, queue group, and stream will become part of your everyday vocabulary.
We'll break down the subject-based routing model, the three communication patterns a single server supports, the JetStream layer as a persistence engine, and the components that make up the NATS ecosystem. Absorb it calmly; episodes 3 through 22 will build on these concepts.
The heart of NATS routing is the subject: a dot-based string that serves as a message address. Real examples:
orders.created
orders.created.eu
payments.charged
notifications.email.sentThere's no upfront declaration — a publisher simply sends to a subject and interested subscribers receive it. The token order describes a hierarchy: orders.created and orders.created.eu are different subjects, with eu being a more specific detail of orders.created.
A subject isn't a topic with partitions like Kafka. It's purely a routing string separated by dots, and it doesn't store any state.
Subscribers can subscribe to many subjects at once using wildcards:
* matches exactly one token.> matches one or more tokens up to the end.nats sub 'orders.*'
nats sub 'orders.>'nats sub 'orders.*' receives orders.created and orders.cancelled, but not orders.created.eu. Meanwhile, nats sub 'orders.>' receives every message starting with orders.. These rules will be covered in depth in episode 4, including their implications for permissions.
The most basic pattern: a publisher sends a message to a subject, and every subscribed subscriber receives a copy. A message with no subscribers is lost in Core NATS — it isn't queued.
publisher --message--> subject:orders.created --> subscriber A
--> subscriber BNATS also provides the request-reply pattern: a sender sends a request to a subject expecting a reply. The server provides an automatic reply subject, and the responding client publishes its answer to that subject. This is the basis for RPC-style patterns between services.
A queue group changes publish/subscribe behavior: among a group of subscribers all subscribed to the same subject, only one member receives each message — round-robin distribution for load balancing.
nats sub orders.created --queue workersThe nats sub orders.created --queue workers command places the subscriber into the workers queue; two or more subscribers in the same queue share the message load in turn. This is the competing consumers pattern that will be covered in full in episode 5.
Core NATS doesn't store messages. JetStream changes that: messages published to a subject can be captured into a stream — a durable message log with a retention policy. The stream is then read by a consumer, either push or pull.
publisher --> subject:orders.> --> stream ORDERS --> consumer --> applicationThe flow above introduces the key JetStream concepts: the stream stores, the consumer reads. Full details on retention, ack, and durability will be covered in episodes 7 through 9.
With JetStream, NATS provides an at-least-once guarantee: messages are acked by the consumer, and if a message isn't acked within a certain time, it's redelivered. This opens the door to workloads that can't afford to lose messages — payments, job queues, event sourcing — without leaving the NATS ecosystem.
nats-server is the daemon that runs everything: Core NATS routing, request-reply, queue groups, and JetStream. Around it are:
/varz, /connz, /jsz, and /subsz.curl -s http://localhost:8222/varz | head -n 20curl -s http://localhost:8222/varz returns JSON containing server status, active connections, and message counts — one of the five observability endpoints that will be covered in episode 18.
Info
Note the separation of roles: nats-server is the runtime, the nats CLI is the administration tool, and client libraries are how applications connect. They're three different binaries, and all three are needed in real-world practice.
Episode 2 equipped you with a mental model of the NATS architecture: subject-based routing with wildcards, three communication patterns supported by a single server, JetStream as the persistence layer, and ecosystem components that complement each other. The terms subject, wildcard, queue group, and stream are no longer foreign vocabulary.
Key takeaways:
* wildcard matches one token, > matches the rest of the tokens.In episode 3 next, we'll discuss setup & first connect — running nats-server directly or via Docker, putting together a minimal configuration, using nats pub, nats sub, and nats server check, and connecting your first client library to the NATS server. Time to get hands-on!