Skip to content

NATS Go Client

Messaging & StreamingMessaging/QueueGo

What it is

The Go client for NATS, a lightweight messaging system supporting publish/subscribe, request/reply and queue groups, with optional persistence via JetStream.

Core NATS is fire-and-forget pub/sub with at-most-once delivery. JetStream layers on persistence, replay and acknowledgement.

Installation

go get github.com/nats-io/nats.go

Getting started

The smallest useful thing you can do with it, and what each part means.

Publish, subscribe and request/reply
nc, err := nats.Connect(nats.DefaultURL,
    nats.MaxReconnects(-1),           // reconnect forever
    nats.ReconnectWait(time.Second))
defer nc.Drain()                      // finish in-flight messages, then close

// Queue group: exactly one member of "workers" receives each message.
sub, _ := nc.QueueSubscribe("orders.created", "workers", func(m *nats.Msg) {
    process(m.Data)
})
defer sub.Unsubscribe()

nc.Publish("orders.created", payload)

// Request/reply with a timeout.
reply, err := nc.Request("inventory.check", sku, 2*time.Second)
Queue groups give you load balancing for free — add another process and the work distributes. Use Drain rather than Close so in-flight messages are handled before shutdown.

Advanced usage

Where the library earns its place over a simpler alternative.

JetStream for durable delivery
js, err := jetstream.New(nc)

_, err = js.CreateStream(ctx, jetstream.StreamConfig{
    Name:     "ORDERS",
    Subjects: []string{"orders.>"},
    Storage:  jetstream.FileStorage,
    MaxAge:   7 * 24 * time.Hour,
})

cons, err := js.CreateOrUpdateConsumer(ctx, "ORDERS", jetstream.ConsumerConfig{
    Durable:   "processor",       // survives restarts
    AckPolicy: jetstream.AckExplicitPolicy,
})

cons.Consume(func(msg jetstream.Msg) {
    if err := process(msg.Data()); err != nil {
        msg.Nak() // redeliver
        return
    }
    msg.Ack()
})
Core NATS drops messages if nobody is listening. JetStream persists them and requires explicit acknowledgement, which is what you want for work that must not be lost.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

nats: no responders available for request
Nothing is subscribed to that subject. Confirm the responder is running and the subject matches exactly.
Messages disappear when consumers restart
That is core NATS behaviour. Use JetStream with a durable consumer for persistence.

Best practices

  • Use Drain instead of Close so in-flight messages complete during shutdown.
  • Use queue groups for horizontal scaling of consumers.
  • Choose JetStream when losing a message is unacceptable; core NATS is at-most-once.
  • Keep subject hierarchies meaningful — wildcards make routing rules much simpler.

Background

Why it exists, and what it was reacting to.

NATS was designed for simplicity and speed where Kafka's durability guarantees are not needed. JetStream later added streaming and persistence for cases that do.