Skip to content

ClientSettings

Constructs a connection. It does not carry the credential — see below.

Field Type Default Meaning
URL string "" Server to reach. Empty only with client.InProcess
Name string "" Connection name in the server's monitoring
MaxReconnects *int -1 Attempt limit. Nil takes the default; negative is unlimited
ReconnectWait time.Duration 2s Pause between attempts
PendingMsgs int 4096 Per-subscription queue bound, in messages
PendingBytes int 32 MiB Per-subscription queue bound, in bytes

The pending limits are the backpressure story

There is no other one. NATS sheds from a full subscription queue rather than delaying the publisher, and reports what it shed. A bound nobody set is a shed nobody sees.

The library's own default is 500,000 messages. This module's is two orders of magnitude smaller, so shedding happens while the traffic causing it is still recent enough to explain.

Both must be positive. A non-positive value means "unlimited" to NATS, so Connect refuses it with ErrUnboundedSubscription rather than handing back the unbounded queue the bound exists to prevent. Message count alone does not bound memory when payload size is uncontrolled, which is why both dimensions are required.

See bound a subscription for how to surface the count.

MaxReconnects defaults to unlimited, and covers the first connect too

Deliberately. A long-running service that stops trying to reconnect has to be restarted by a person to recover from a broker outage it would otherwise have survived unattended.

The initial connection is not exempt. Start succeeds against a broker that is not there yet and keeps trying under this same policy, so a briefly unavailable cluster does not stop an application booting. Setting MaxReconnects: 0 opts back into fail-fast, at start-up as afterwards — this module enforces that coupling itself, because nats.go treats the two independently.

Waiting for the connection

Because Start returns while the client is still trying, a caller that needs a connection waits for one:

if err := cli.WaitReady(ctx); err != nil {
    return fmt.Errorf("nats: never became ready: %w", err)
}

It returns nil once connected, and an error when the context expires, when the client is stopped while waiting, or when the retry policy gives up. It returns immediately for a client that is already connected.

WaitReady is asked once, at start-up. Readiness is the ongoing question — "is it connected right now" — and is what the controller polls. They are deliberately not the same call: a start-up gate that also claimed to report current health would go true once and stay true through every subsequent outage.

Zero means zero, and that is why it is a pointer

NATS reads 0 as "do not reconnect". An earlier version stored this as a plain int and defaulted 0 to unlimited, so a service configured to fail fast stayed alive and disconnected instead — the opposite of what it asked for, and silent.

Nil is "not set". Use nats.Reconnects(0) to mean it.

CredentialSource

type CredentialSource func(ctx context.Context) (string, error)

A function rather than a string, so the secret is resolved at connect time rather than carried around, and so this module depends on no particular credential store.

The estate's ladder — an environment variable name, a keychain reference, a literal, then a well-known variable — is composed by the calling application and handed in. That is the same shape forge.CredentialSource takes, for the same reason: precedence is the consumer's decision, and a library that decides it is a second statement of something the estate already states once.

StaticCredential(token) exists for tests and for a caller that resolved the secret by some route this module has never heard of.

Passing nil is accepted and should only ever be done for an in-process server.

Two refusals protect the credential

A URL carrying userinfo (nats://token@broker) is refused with ErrCredentialInURL — it would put a secret in a struct that gets logged and committed.

A credential over an unencrypted scheme is refused with ErrInsecureCredential. A NATS token is bearer material; over nats:// it crosses the network in plaintext.

The credential is resolved once

It is read at connect time and installed for the life of the connection, so every reconnect reuses it. After a rotation, reconnects keep presenting the stale token until NATS stops trying, at which point Liveness reports the connection closed. Rotation currently requires a new client. Tracked.