Learn NATS - JetStream Consumers
Series/Learn NATS/Episode 9
Episode 9 of 23

Learn NATS - JetStream Consumers

This episode covers JetStream consumers in full: the difference between pull and push consumers, durable versus ephemeral, ack and nack semantics, ackWait, max delivery for redelivery, as well as deliver_policy and replay for determining the starting point of reads.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Introduction

Episode 8 configured how messages are stored in a stream. Episode 9 configures how messages come out: the consumer. If the stream is a pool, the consumer is the faucet — and NATS gives you very fine-grained control over that faucet.

We'll break down the two consumer types, the difference between durable and ephemeral, then the entire delivery semantics: ack, nack, ackWait, max delivery, deliver_policy, and replay. Study this episode well because it becomes the foundation of work queues and streaming pipelines.

Consumer Types: Pull vs Push

Push Consumer

A push consumer makes the server deliver messages directly to a client subscription without being asked. Ideal for small numbers of consumers that are always online and use regular subscriptions.

Create a push consumer
nats consumer add ORDERS PROCESSOR --deliver subject "processor.orders" --ack explicit

The nats consumer add ORDERS PROCESSOR --deliver subject "processor.orders" command creates a PROCESSOR push consumer that delivers messages to the processor.orders subject. The application just subscribes to that subject to receive the message stream.

Pull Consumer

A pull consumer makes the client request messages one at a time or in batches. This is the best pattern for many workers that need to control their pace and apply backpressure.

Create a pull consumer
nats consumer add ORDERS WORKER --pull --ack explicit

--pull marks the consumer as pull. Clients request messages with fetch or next, so load is only received when a worker is ready. Episode 11 will use a pull consumer as the core of a work queue.

CharacteristicPushPull
Delivery directionServer to clientClient requests
Speed controlServer flow controlFull client control
Consumer countFewMany, up to hundreds
BackpressureNeeds rulesNatural

Durable vs Ephemeral Consumers

Durable Consumer with Persistent State

A durable consumer has a name and state stored by the server: read position, in-flight messages, and ack history. If the application restarts, the consumer continues from its last position.

Durable consumer
nats consumer add ORDERS PROCESSOR --durable PROCESSOR --pull --ack explicit

--durable PROCESSOR gives the consumer a name. Its state survives on the server until removed with nats consumer rm.

Ephemeral Consumer for One-Off Use

An ephemeral consumer is created without a name and vanishes when the client connection closes. Suited for temporary tasks: brief analyses, prototypes, or jobs that don't need to continue.

Ephemeral consumer
nats consumer add ORDERS TMP --ephemeral --pull --ack explicit

The --ephemeral option creates a temporary consumer that the server automatically removes when the client disconnects. For production that needs guaranteed reprocessing after a restart, always use durable.

Info

A practical rule: durable for services that must always continue their read position, ephemeral for one-off utilities. Durable consumers require state on the server, so don't create them without limit — each durable has a unique name.

Delivery Semantics: Ack and Redelivery

Ack, Nack, and AckWait

Ack marks a message as successfully processed; nack asks the server to redeliver immediately; ackWait is the maximum time to wait for an ack before a message is considered failed and redelivered automatically.

Set ackWait and max delivery
nats consumer add ORDERS PROCESSOR --pull --ack explicit --ack-wait 30s --max-deliver 5

--ack-wait 30s gives the worker 30 seconds to ack, and --max-deliver 5 limits redelivery to at most 5 times before the message goes to the dead letter. These two values prevent messages from being stuck forever.

Redelivery and Dead Letters

If a worker keeps failing to ack, the message is redelivered until max_deliver is reached:

Check messages awaiting ack
nats consumer report ORDERS

nats consumer report ORDERS shows how many messages are pending and how many times they've been redelivered. A high redelivery count is a signal of a problematic worker — we'll cover this as troubleshooting in episode 19.

Deliver Policy and Replay

Where a Consumer Starts Reading

deliver_policy determines the first message received by a newly created consumer:

  • new: only messages arriving after the consumer is created.
  • all: all messages from the beginning of the stream.
  • last: the last message before the consumer was created.
  • last_per_subject: the last message per subject.
Consumer starting from the beginning
nats consumer add ORDERS REPLAY --pull --deliver all --replay original

--deliver all makes the consumer read the entire stream history, and --replay original delivers messages with pauses matching their original pace. The opposite, --replay instant, delivers as fast as possible.

start_sequence and start_time

For even more precision, specify the starting point explicitly:

Consumer from a specific sequence
nats consumer add ORDERS FROM_SEQ --pull --deliver by_start_sequence --start-sequence 5000

--start-sequence 5000 starts reading from the message with sequence 5000 — useful for replaying data after a certain event. Alternatively, --deliver by_start_time --start-time "2026-08-10T00:00:00Z" starts from a specific timestamp.

Conclusion

Episode 9 gave you full control over how messages are delivered from a stream: choosing a push or pull consumer, deciding between durable and ephemeral, configuring ack, nack, ackWait, and max delivery for redelivery, and setting deliver_policy and replay to determine the starting point of reads.

Key takeaways:

  • A push consumer delivers automatically; a pull consumer waits for client requests.
  • Durable keeps state and continues position; ephemeral vanishes when the connection closes.
  • Ack marks success, nack requests redelivery, ackWait bounds the wait time.
  • max_deliver limits the redelivery count before the dead letter.
  • deliver_policy selects where a consumer starts: new, all, last, or sequence.
  • Original replay follows the original pace; instant delivers as fast as possible.

In episode 10 next, we'll discuss KV store & object store — key-value buckets with TTL and history, watchers for change notifications, revision-based safe updates, then object stores for storing large files in chunks, all running on top of JetStream. Your application data starts living inside NATS.