Ensure JetStream is enabled on the NATS server (--jetstream flag or jetstream: enabled in config); create a stream that captures your subject(s) by calling js.AddStream with Name, Subjects (e.g., ['orders.>']), Storage (file or memory), and retention policy
Create a durable consumer on the stream using js.AddConsumer or the consumer API with Durable set to a stable name; set DeliverPolicy (all, last, new, or by start time/sequence), AckPolicy to explicit, and MaxDeliver to limit redelivery attempts
Subscribe using the durable consumer name via js.Subscribe or js.PullSubscribe; for pull consumers call Fetch(n) in a loop to receive batches of messages — pull consumers give the application full control over consumption rate
Acknowledge each message explicitly (msg.Ack()) after successful processing; use msg.Nak() to request immediate redelivery, or msg.NakWithDelay(duration) to back off before redelivery; use msg.Term() to permanently discard a message without redelivery
Set the MaxDeliver limit on the consumer and configure a dead-letter stream: route terminated or MaxDeliver-exceeded messages to a separate stream using an advisory subject filter or a consumer with a separate subject transform
Monitor consumer lag (NumPending) and redelivery rate via the NATS monitoring endpoint or nats consumer info <stream> <consumer> CLI command; high NumPending with low throughput indicates a stalled consumer
Known gotchas
NATS JetStream uses an internal ack wait timeout (AckWait, default 30 seconds) — if the consumer does not ack within AckWait, the message is redelivered even if the consumer is still processing it; set AckWait longer than your maximum processing time or send msg.InProgress() to reset the timer
Durable consumers retain state on the server; deleting and recreating a consumer with the same name resets its position — use a new durable name or explicitly set the start sequence when resuming from a known offset
Push consumers can overflow a slow subscriber's buffer causing dropped messages; pull consumers are preferred for load-sensitive processing because the application controls when it asks for more messages
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp