NATS Server Documentation
repository·main·Indexed Apr 15, 2026
https://github.com/nats-io/nats-serverOfficial documentation for nats-server, a high-performance, secure messaging system for distributed systems and part of the CNCF. Supports MQTT v3.1.1, JetStream persistence, and over 40 client languages. Includes details on stream imports, shadow subscriptions, subscription limits, client disconnection cleanup, and JetStream consumer management with priority policies and delivery options.
What's inside nats-server
Query Server Statistics and State
mainAccess the following methods to retrieve real-time statistics about the server's connections and performance:
NumClients(): Returns the number of registered clients.NumRoutes(): Returns the number of registered routes.NumRemotes(): Returns the number of registered remotes.NumLeafNodes(): Returns the number of leaf node connections.NumSubscriptions(): Returns the total number of active subscriptions.NumSlowConsumers(): Returns the total count of slow consumers.NumStalledClients(): Returns the total number of times clients have been stalled.NumStaleConnections(): Returns the number of stale connections.
For granular breakdowns, use the specific stats methods:
NumSlowConsumersClients(),NumSlowConsumersRoutes(),NumSlowConsumersGateways(),NumSlowConsumersLeafs()NumStaleConnectionsClients(),NumStaleConnectionsRoutes(),NumStaleConnectionsGateways(),NumStaleConnectionsLeafs()
Sources:
server/server.goNATS Server Overview
mainNATS is a simple, secure, and performant communications system for digital systems, services, and devices. It is part of the Cloud Native Computing Foundation (CNCF) and supports over 40 client language implementations. The server can run on-premise, in the cloud, at the edge, or on devices like a Raspberry Pi.MQTT Implementation Overview and Concepts
mainCalculate Pending Messages for Consumers
mainThe consumer calculates the number of pending messages (
numPending) based on the stream state and delivery policy. This is used to inform clients about how many messages are available for delivery.Calculation Logic:
- The consumer checks the stream's
LastSeqand compares it to the consumer'ssseq(stream sequence). - If
sseqexceedsLastSeq, the pending count is reset to 0. - For filtered consumers, the calculation uses
NumPendingMultiwith subject filters. - For
DeliverLastPerSubjectpolicy, the calculation is adjusted to reflect the last message per subject.
Methods:
streamNumPendingLocked(): Acquires the consumer lock and callsstreamNumPending().streamNumPending(): Calculates the pending count based on delivery policy and filters.calculateNumPending(): Performs the actual calculation using the stream store.checkNumPending(): Validates the pending count against the stream state to prevent reporting more messages than exist.
Example Usage:
// Get the number of pending messages pending, err := consumer.StreamNumPendingLocked() if err != nil { // Handle error }Important Notes:
- The
checkNumPending()method includes sanity checks to handle race conditions during stream deletion or message removal. - If the consumer is not filtered, the calculation uses the stream's
NumPendingmethod with an empty filter. - For filtered consumers, the calculation uses
NumPendingMultiwith the configured subject filters.
// Example: Calculate pending messages func (o *consumer) streamNumPending() (uint64, error) { if o.mset == nil || o.mset.store == nil { o.npc, o.npf = 0, 0 return 0, nil } npc, npf, err := o.calculateNumPending() if err != nil { return 0, err } o.npc, o.npf = int64(npc), npf return o.numPending(), nil } // Example: Check pending count sanity func (o *consumer) checkNumPending() (uint64, error) { if o.mset != nil && o.mset.store != nil { var state StreamState o.mset.store.FastState(&state) npc := o.numPending() if o.sseq > state.LastSeq { o.npc = 0 } else if npc > 0 { o.npc = int64(min(npc, state.Msgs, state.LastSeq-o.sseq+1)) } } return o.numPending(), nil }Sources:
server/consumer.go- The consumer checks the stream's
MQTT Implementation Overview
mainThe NATS Server implements the MQTT v3.1.1 specification. This guide outlines the core concepts, lifecycles, and how the server utilizes JetStream to manage MQTT sessions, messages, and subscriptions.Check Server Header Support
mainUse
supportsHeadersto determine if the server is configured to support NATS message headers. This returnsfalseif theNoHeaderSupportoption is enabled or if the server instance is nil.Usage:
if server.supportsHeaders() { // Safe to use headers in messages } else { // Headers are disabled }Returns:
bool:trueif headers are supported,falseotherwise.
Sources:
server/server.goUsage
main- Create stream in source account:
_, err := js.AddStream(&nats.StreamConfig{ Name: "ORDERS", Subjects: []string{"foo"}, Storage: nats.MemoryStorage, })- Create consumer with delivery subject:
_, err = js.AddConsumer("ORDERS", &nats.ConsumerConfig{ DeliverSubject: "deliver.ORDERS", AckPolicy: nats.AckExplicitPolicy, })- Subscribe in importing account with remapped subject:
// Messages published to "foo" arrive as "bar.ORDERS" in importing account sub, err := nc2.SubscribeSync("bar.ORDERS")The
tofield in the import configuration remaps the subject from the source account to the importing account's namespace.imports [ { stream: { account: JS, subject: "deliver.ORDERS" }, to: "d.*" } { stream: { account: JS, subject: "foo.*" }, to: "bar.*" } ] // Consumer receives messages with remapped subject sub, err := nc2.SubscribeSync("bar.ORDERS")Sources:
server/jetstream_test.goUsage
mainvar resp JSApiAccountPurgeResponse ncsys := natsConnect(t, s.ClientURL(), nats.UserCredentials(sysCreds)) defer ncsys.Close() m, err := ncsys.Request(fmt.Sprintf(JSApiAccountPurgeT, accpub), nil, 5*time.Second) require_NoError(t, err) err = json.Unmarshal(m.Data, &resp) require_NoError(t, err) require_True(t, resp.Initiated)Usage
mainWhen publishing messages, set the
JSMsgIdheader:m := nats.NewMsg("foo.1") m.Header.Add(nats.JSMsgId, "unique-id-1") m.Data = []byte("Hello DeDupe!") resp, _ := nc.RequestMsg(m, 100*time.Millisecond)If a message with the same ID is sent within the
Duplicateswindow, the server returns aPubAckwithDuplicate: trueand does not store the message again.Get Client Account and RTT
mainAccess the account associated with a client and retrieve its Round-Trip Time (RTT) value safely using locks.
Functions:
Account() *Account: Returns the account associated with the client. Returnsnilif the client isnil.getRTTValue() time.Duration: Returns the current RTT value. Protects access with the client lock.
Usage: These are safe, public methods to inspect client state without needing to manage locks directly.
Sources:
server/client.goSetup WorkQueue Source
main// Create source stream _, err := js.AddStream(&nats.StreamConfig{ Name: "FOO", Subjects: []string{"foo"}, }) // Create workqueue stream with source _, err = js.AddStream(&nats.StreamConfig{ Name: "TEST", Retention: nats.WorkQueuePolicy, Sources: []*nats.StreamSource{{Name: "FOO"}}, }) // Add consumer _, err = js.AddConsumer("TEST", &nats.ConsumerConfig{ Durable: "dur", AckPolicy: nats.AckExplicitPolicy, })