Skip to main content

Where Next

You started this chapter with the Acme clients connecting on bare defaults: a single URL, no name, no plan for a server going away. You end it with an order-svc that opens against a server pool, reconnects with backoff and jitter, drains in-flight work on shutdown, bounds its subscribers' memory, retries requests safely, and presents credentials over a CA-validated link. That covers the whole arc of the chapter.

This page doesn't teach anything new. It collects the model you built into one place and points you at the chapters and Reference that take it further.

The core model in one sentence

Every page in this chapter moved the same object, the connection, through one more state safely. That is the one point to take away from this chapter.

The connection is a state machine. It lives in a small set of states: DISCONNECTED, CONNECTING, CONNECTED, RECONNECTING, DRAINING, CLOSED. Every fault this chapter survives is one well-defined edge between them. A server dying moves a CONNECTED client to RECONNECTING. A SIGTERM moves it to DRAINING and then CLOSED. A blocked dial keeps it in CONNECTING until the timeout fires.

Each page added exactly one transition the Acme clients couldn't handle before. Connecting taught the CONNECTING → CONNECTED edge and the handshake that walks it. Reconnection taught the CONNECTED → RECONNECTING → CONNECTED loop with backoff and jitter. Drain & Shutdown taught the CONNECTED → DRAINING → CLOSED edge that loses no work. Slow Consumers kept a CONNECTED client healthy under load instead of letting a subscriber's buffer grow without bound. Request-Reply Resilience made a single request() call survive a slow or absent responder. TLS & Auth secured the edge into CONNECTED so the link is encrypted and the client is who it claims to be.

Those six mechanisms all act on one machine. Everything else is a refinement of those edges: the exact flags, the defaults, the per-language spelling.

Where the details live

The chapter is unversioned and concept-first. The exact option names, defaults, and ranges live in Reference, which is versioned and exhaustive. When you need the precise type of a connection option or the full list of error codes a -ERR can carry, that's where to look.

Reference documents the full set of connection options. Here we covered only the ones that change how a connection behaves under fault; the handoff phrases throughout this chapter all point into that root.

Sibling deep dives

This chapter stops at the edge of the client on purpose. Where a page reached a server-side fact, a JetStream position, or an issued credential, it named the gap and linked out. Those links lead to the deep dives that own what this one only consumes.

The Topologies deep dive explains the server pool this chapter only connects to: why a server goes away, how the n1/n2/n3 cluster forms, and what a client's disconnect looks like from the server side. Resilient Clients treats "the server is gone" as a given fact, while Topologies explains why it happens.

The JetStream deep dive owns what happens to a consumer's position across a reconnect. This chapter re-subscribes the connection; JetStream → Acknowledgment covers what a consumer's position does and whether in-flight work is repeated or resumed.

The Security deep dive issues the credentials and the CA this chapter loads. TLS & Auth consumes the order-svc .creds and the cluster CA; Security shows how both are created.

The Services deep dive builds the request-reply pattern into a framework with built-in retries. If you found yourself wrapping every request() in backoff, that's the next step.

The Monitoring deep dive watches the same connections from the server side: the slow_consumers metric, the advisories, and the health endpoints that tell you a client is struggling before its users do.

Where you are

This is the end of the chapter. The arc is complete, and this page adds no new scenario state. The order-svc publisher, the warehouse, notifications, and analytics subscribers, and the JetStream consumers are still running in your session exactly as you left them on the previous page, now with production connection options on every one.

You hold the core model: a connection is a state machine, every fault is a transition, and each option in this chapter shapes one edge. That model is the floor for running any NATS client in production.

Production checklist

Every page in this chapter closed with a Pitfalls section. This collects the action items from all of them in one place: a last pass before you trust a connection with real orders. Each group links back to the page that explains the why.

Connecting — see Pitfalls

  • Pass the whole server pool (several URLs, or several IPs behind one name) so a single unreachable server isn't fatal at connect time.
  • Set a deliberate connect timeout so a blocked dial costs one timeout, not a hung startup that looks dead.
  • Keep messages under the server's max_payload and store large bodies elsewhere; an oversized publish fails before it's sent, and that's not a connection problem.

Reconnection — see Pitfalls

  • Set MaxReconnect to -1 on a long-lived service so a long outage doesn't exhaust the default 60 attempts and leave the connection CLOSED.
  • Watch the reconnect-error callback so a long outage is loud in your logs, not a silent give-up.
  • Keep a non-zero wait and always keep jitter; a zero or fixed delay either spins the CPU or stampedes the survivor in lockstep.
  • Catch ErrReconnectBufExceeded and back off publishing; the reconnect buffer is 8 MB, not infinite, and the publish that overflows it fails.
  • Lower the ping interval under heavy load so you catch a wedged connection in seconds, not the default two minutes.

Drain & Shutdown — see Pitfalls

  • Drain last, not first; a publish after Drain() returns ErrConnectionDraining and never sends.
  • Size the drain timeout to your slowest handler's latency; a timeout shorter than the handler discards the remaining in-flight work.
  • Ack JetStream in-flight messages before a core drain; a connection drain does not handle a consumer's ack position for you.

Slow Consumers — see Pitfalls

  • Always set pending limits on a subscription that does real per-message work; the generous defaults (500,000 messages, 64 MB) are a backstop, not a tuning, and a high-rate subject fills them in seconds.
  • Size the pending limit to the handler's latency and the subject's peak rate, not to caps sized for someone else's workload.
  • Always set the async-error callback and log the slow-consumer error loudly; a nil one drops every overflow message silently.
  • Tell a local drop apart from a server-side disconnect; watch the async-error rate and the disconnect rate separately, since each points at a different fix.

Request-Reply Resilience — see Pitfalls

  • Measure the responder's p99 and set the request timeout to two or three times it; a timeout under the real latency retries a responder that was about to answer.
  • Handle no-responders and a timeout separately; an absent responder warrants a backoff, a slow one warrants a fast retry.
  • Key retries by order_id and de-dupe on the responder so a re-sent request is a no-op, not a double action.
  • Cap the retry count and add jitter; an unbounded retry loop hammers a struggling responder in lockstep.

TLS & Auth — see Pitfalls

  • Load credentials from a file or environment and never commit a .creds to source.
  • Always supply the CA certificate in production; skip-verify TLS encrypts the link but authenticates nothing.
  • Refresh a credentials JWT before it expires, or monitor the auth-error rate, so an expired token doesn't silently break the next reconnect.
  • Rotate credentials with a fresh connection and drain the old one; reloading a creds file mid-connection races the live link.

See also

  • Reference — every connection option, default, and error code, versioned and exhaustive.
  • Topologies deep dive — the server pool this chapter only connects to, explained from the server side.
  • Security deep dive — issuing the credentials and CA this chapter consumes.