Replication and R=3
The last page elected leaders, so the cluster now has a meta leader and,
once you create a stream, a leader for that stream's RAFT group. This
page uses those leaders: it follows a single order from
order-svc into the ORDERS stream and shows exactly when that write
becomes safe to lose a server over.
The surviving node loss page in
the JetStream chapter gave you the one-line version: R=3 keeps three
copies, so the loss of one server costs nothing. This page explains the
mechanism behind that guarantee. It introduces two ideas: quorum
commit, how the leader turns one write into a committed entry across
the group, and the consistency you get back from it.
R=3 means three peers in one RAFT group
A stream's replica count is the number of copies the cluster keeps.
R=3 keeps three. Each copy lives on a different server, and the three
servers holding the copies form a single RAFT group, the same kind of
consensus group the last page elected a leader for.
You set the count when you create the stream. On the east cluster,
one flag turns the single-server ORDERS of the JetStream chapter into
a three-peer stream:
- CLI
#!/bin/bash
# Create the ORDERS stream as an R=3 stream on the `east` cluster, then publish
# one order and read back which server leads the stream and which servers hold
# the copies.
#
# This assumes the three `east` servers from the Topologies chapter are running,
# each with JetStream enabled:
# nats-server -c n1-east.conf
# nats-server -c n2-east.conf
# nats-server -c n3-east.conf
#
# Point the CLI at any server in the cluster. The cluster routes the request to
# the stream leader wherever it currently lives.
export NATS_URL="nats://127.0.0.1:4222,nats://127.0.0.1:4223,nats://127.0.0.1:4224"
# Create ORDERS with three replicas. --replicas=3 is the only line that differs
# from the single-server create in the JetStream chapter. If ORDERS already
# exists at R=1, raise it instead: nats stream edit ORDERS --replicas=3
nats stream add ORDERS \
--subjects "orders.>" \
--replicas=3 \
--defaults
# Publish one order as order-svc would. The PubAck returns only after the
# leader has the write committed to a quorum (itself plus one follower).
nats pub orders.created \
'{"order_id":"ord_8w2k","customer":"acme-co","total_cents":4200,"ts":"2026-05-22T10:14:22Z"}'
# Confirm the replica count and the cluster layout that R=3 produced.
nats stream info ORDERS
# Expected Cluster Information section:
#
# Cluster Information:
#
# Name: east
# Cluster Group: S-R3F-xK2p9aLm
# Leader: n1-east
# Replica: n2-east, current, seen 0.00s ago
# Replica: n3-east, current, seen 0.00s ago
--replicas=3 is the whole change. The application code doesn't move:
order-svc publishes the same payload to the same subject whether the
stream is R=1 or R=3.
{"order_id":"ord_8w2k","customer":"acme-co","total_cents":4200,"ts":"2026-05-22T10:14:22Z"}
What changes is underneath. The stream now has a leader (one of
the three peers, here n1-east) and two followers, n2-east and
n3-east. Every write goes through the leader. The followers never
take writes directly; they receive them from the leader.
Three is the minimum for production, and a stream
supports at most R=5. The reasoning for which odd count to choose
belongs to surviving node loss.
Here we follow what one write does once the count is three.
A write commits by quorum
When order-svc publishes orders.created, the message reaches the
stream leader, n1-east. The leader does not return success on storing
it locally; it runs a short sequence first.
The leader appends the write to its own log: an ordered,
append-only record of every operation the group has agreed on. Appending
is local and not yet durable across the group: only n1-east has the
entry so far.
The leader then sends an append entry to each follower: the
replication message that says "add this entry to your log at this
position." n2-east and n3-east receive it, write it to their own
logs, and reply with an ack.
The leader counts acks. A write is committed once a quorum,
a majority of the peers, holds the entry. For R=3, a quorum is two
of three. The leader is itself one of the two, so it needs just one
follower's ack to reach quorum. The instant the first follower acks,
the entry is committed.
Commit is the point at which durability is reached. A committed entry
survives the loss of any single server, because it already lives on a
majority. This is what makes the PubAck that order-svc receives a
real guarantee: the leader returns it only after the write commits, so
a PubAck means the order already survived the chance of a single-node
failure before you heard back.
The third peer isn't on the critical path. n3-east may ack a moment
later, or be briefly behind; the write committed without waiting for it.
That's the point of a quorum: the group makes progress as long as a
majority is reachable, even if not all peers are.
Followers apply what the leader commits
Committing records that a quorum has the entry. It doesn't yet put the order into each peer's copy of the stream. That last step is apply: copying a committed entry from the log into the stream store, where consumers can read it.
The leader tracks a commit index, the position up to which entries are committed. It is included on the next append entry or heartbeat, so followers learn "everything up to here is committed; apply it." Each follower then applies those entries to its own stream store in the same order the leader did.
Order is what the group guarantees here. Every peer applies the same
entries in the same sequence, so all three copies of ORDERS converge
on the identical message log. A follower can lag the leader by a few
entries, but it never reorders them and never skips one.
Here's one write from order-svc moving through that whole sequence
(publish, append entry, ack, commit at quorum, apply):
You'll find the full set of RAFT replication parameters (append-entry batching, heartbeat intervals, log compaction) in Reference. All you need here is the append → quorum → commit → apply shape.
The consistency you get
Quorum commit gives a specific, nameable consistency, and you should know its boundaries before you build on it.
Reads from the leader are read-after-write. The leader holds every
committed entry and assigns every sequence number, so once a PubAck
returns, a read from the leader sees that order. There's no window
where your own just-acked write is missing.
Reads from a follower can lag. A follower applies committed entries
slightly after the leader does, so a direct read from n2-east or
n3-east might not yet show the most recent order, even though that
order is already committed and safe. The data is correct but slightly
behind. For read-after-write, read from the leader.
This is the trade R=3 makes on purpose. Rather than promising that
every copy is identical at every instant, it promises that every copy
converges, in order, and that a committed write survives one server
loss. When you need to confirm where the copies actually stand, the
Cluster block of nats stream info reports each replica's status and
how far behind it is, which is exactly the next section's first trap.
Pitfalls
These are three common mistakes the first time you trust a replicated stream. Each is scoped to this page's two ideas: how a write commits, and the consistency it gives back.
R=1 has no copy. A stream at R=1 lives on exactly one server.
There's no second peer, so there's no quorum and nothing to commit
to beyond the one log. If that server's disk is lost, the order is
lost too, with no failover and no recovery. Only R≥3 survives a node
loss.
Don't run real orders at R=1; the why-three reasoning is covered on
surviving node loss.
A follower may lag, so a follower read can be stale. A committed write is safe, but it reaches each follower's stream store slightly after the leader applies it. A direct read aimed at a follower can therefore return data that's correct but not the newest. Don't assume any peer is current just because the write was acked. For read-after-write, read from the leader; to confirm a copy is caught up, read its status before you trust it.
Check the leader and each replica's lag before assuming all copies are current:
- CLI
#!/bin/bash
# Read the Cluster block of `nats stream info` to check that every copy of
# ORDERS is current before trusting the stream. This is the handling step for
# the "a replica may lag" pitfall: do not assume all three copies hold the same
# data — read the lag and confirm it.
#
# Assumes the `east` cluster is running and ORDERS is an R=3 stream (see
# createR3.sh). Point the CLI at any server in the cluster.
export NATS_URL="nats://127.0.0.1:4222,nats://127.0.0.1:4223,nats://127.0.0.1:4224"
# Ask the cluster who leads ORDERS and how its followers are doing. The Cluster
# Information block names the LEADER (every write lands there) and lists each
# Replica with its status.
nats stream info ORDERS
# Read the Cluster Information section carefully:
#
# Cluster Information:
#
# Name: east
# Cluster Group: S-R3F-xK2p9aLm
# Leader: n1-east
# Replica: n2-east, current, seen 0.00s ago
# Replica: n3-east, current, seen 0.00s ago
#
# "current" means the follower has applied every committed entry — it is up to
# date with the leader. A healthy R=3 stream shows every Replica "current" with
# a small "seen" age.
#
# A follower that is catching up shows "outdated" and a non-zero lag instead:
#
# Replica: n3-east, outdated, seen 0.12s ago, 4,512 operations behind
#
# If a replica is outdated, do not treat it as a current copy. Read from the
# leader for read-after-write, and wait for "current" before trusting that copy
# to survive a node loss. A persistent lag points at a slow disk or a saturated
# route between peers.
A PubAck proves quorum, not full replication. The leader returns
the PubAck the instant a quorum holds the entry: for R=3, the
leader plus one follower. The third peer may still be catching up at that
moment. That's correct and safe: the write already survives one node
loss. But don't read a PubAck as "all three copies are identical
right now." If you need every copy current (say, before deliberately
taking a server down), verify each replica shows current in
nats stream info first.
Where you are
The ORDERS stream now runs R=3 on the east cluster: a leader on
n1-east and followers on n2-east and n3-east, all carrying the
same order log.
What changed is your model of a write:
- A write appends to the leader's log, replicates as an append entry
to followers, and commits once a quorum holds it: two of three for
R=3. - Followers apply committed entries in order, so all three copies converge on the identical log.
- A
PubAckmeans the order survived the loss of one server before you heard back. - Read-after-write comes from the leader; follower reads may lag.
What's next
The stream is replicated, but the cluster chose where its three copies landed. The next page makes that choice yours: placement constrains a stream's replicas to a cluster and to servers carrying matching tags, and hints which peer should lead first.
Continue to Placement.
See also
- Surviving node loss — the
one-page operator intro to
R=3and storage durability. - Reference → Stream Configuration —
the full
StreamConfig, including every replica option. - Mirrors and sources — copying a stream's data on purpose, across clusters and for DR.