Retry and Dead-Letter Queues in NATS JetStream with Go

In the previous post we built a simple publisher and worker on JetStream. But that worker assumed processing always succeeds. In real systems some messages fail every single time, and if you do nothing they either retry forever or get lost. This post adds three things: Limiting attempts with MaxDeliver Spacing out attempts with BackOff and NakWithDelay Routing “poison” messages to a dead-letter stream I tested every behavior below against an embedded NATS server (with JetStream) and the nats.go client, and the outputs come from that run. ...

October 18, 2026 · 4 min · Roham

A Simple Publisher and Worker with NATS JetStream in Go

When I want to really understand a concept, I build the smallest runnable example of it. This time it was NATS JetStream. The result is go-nats-demo: a publisher, a worker and NATS itself, all wired together with Docker Compose. Why JetStream? Core NATS only delivers messages to subscribers that are connected at that moment. If the worker is down, the message is gone. JetStream adds persistence on top of NATS: messages are stored in a stream, and consumers can read them later and acknowledge them. ...

October 18, 2026 · 3 min · Roham