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.

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.
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.
nats consumer add ORDERS PROCESSOR --deliver subject "processor.orders" --ack explicitThe 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.
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.
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.
| Characteristic | Push | Pull |
|---|---|---|
| Delivery direction | Server to client | Client requests |
| Speed control | Server flow control | Full client control |
| Consumer count | Few | Many, up to hundreds |
| Backpressure | Needs rules | Natural |
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.
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.
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.
nats consumer add ORDERS TMP --ephemeral --pull --ack explicitThe --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.
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.
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.
If a worker keeps failing to ack, the message is redelivered until max_deliver is reached:
nats consumer report ORDERSnats 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 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.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.
For even more precision, specify the starting point explicitly:
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.
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:
max_deliver limits the redelivery count before the dead letter.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.