Request-reply is two messages and a mailbox
I needed NATS for work, so I built the smallest thing that would force me to learn request-reply: a responder that answers pong on the ping subject, and a requester that asks it. (ping-pong-responder)
I assumed request-reply was a broker primitive. Some special verb the server understood.
It’s two ordinary pub/sub messages. Before the requester publishes to ping, it invents a throwaway subject called _INBOX.<random>, subscribes to it, and stamps it on the outgoing message as the reply address. The responder publishes its answer to that inbox. The requester is already listening there. That’s the whole trick: two fire-and-forget messages and a mailbox the client made up for one exchange.
I didn’t buy it until I watched it happen. Third terminal:
nats sub ">"
That subscribes to every subject. Run the requester again and two lines show up: the message on ping, and the reply on some _INBOX.AB12CD... that nobody declared. The mailbox is right there on the wire. Seeing it is what made the rest make sense. The 5-second timeout and the “no responders” error are both just things that happen to a normal subscription when nobody answers in time.
The other thing that got me was scaling. In a real system a responder isn’t one process. It’s a service, and a service runs as many instances across a cluster, scaling up and down with load. Every one of those instances subscribes to the same ping subject. Plain pub/sub delivers each message to all of them, so a single request makes every instance do the work and reply. I want exactly one of them to.
That’s the problem queue groups solve. Subscribe under a queue name and NATS treats the whole group as one logical consumer: it picks a single member and delivers the message there, once. Ten instances in the group, one reply per request. Scaling from one to ten is a queue name on the subscription plus more processes, and the requester never finds out. It publishes to ping and waits on its inbox whether one instance is listening or fifty are.
Turns out “request-reply” and “horizontally scaled service” were both just subscriptions wearing a hat. 😅