Learning objective. Understand why loss, reordering, and ACK delay hurt more on a long-RTT path: how the packet- and time-threshold rules interact with reordering, how reported ACK delay is removed from the RTT estimate, and why every PTO-driven retransmit costs a full, growing round trip.
The thing that changes on a long path: the cost of being wrong #
The loss-detection machinery of §3.2 is identical at any RTT. What changes on a long path is the cost of each recovery event: a retransmit that clears in 2 ms on a LAN costs 200 ms over satellite, and a mistaken retransmit wastes that same 200 ms plus congestion-window room. On long paths, recovery accuracy and timing dominate, so this section re-reads three mechanisms (thresholds, ACK delay, and the PTO) through the high-latency lens.
Reordering versus the loss thresholds #
QUIC declares a packet lost by one of two triggers ([RFC 9002 §6.1]): the packet threshold —
a packet is lost once 3 later-numbered packets are acknowledged (kPacketThreshold = 3,
[RFC 9002 §6.1.1]) — or the time threshold, once it is older than
max(9/8 × max(smoothed_rtt, latest_rtt), kGranularity) (kTimeThreshold = 9/8,
[RFC 9002 §6.1.2]). Both exist to tolerate reordering: a packet that arrives a little late, or
a little out of order, is not immediately called lost.
The trouble is that neither threshold scales with the degree of reordering on a path. If a
network can reorder a packet by more than 3 positions (common on multi-path or load-balanced
long-haul links), the packet threshold fires while the packet is merely in transit, and the sender
retransmits something that was never lost. That spurious retransmission costs a full RTT of
useless data and needlessly cuts the congestion window. The time threshold's 9/8 factor is the
reordering cushion in the time domain, and it does scale with RTT (via smoothed_rtt), which is
why on high-reorder paths the time threshold is the gentler of the two. QUIC's design accepts a
small spurious-retransmit rate as the price of fast recovery; on a long path that price is higher,
which is the whole reason §8.3 and §8.4 work to avoid needing recovery at
all.
ACK delay and the RTT estimate #
A receiver may hold an ACK briefly to batch it, and it reports how long it waited in the ACK frame's ACK Delay field ([RFC 9000 §19.3]). The sender must remove that reported delay before it pollutes the RTT estimate, because the delay is the receiver's processing choice, not the network's latency. The rule is precise ([RFC 9002 §5.3]):
adjusted_rtt = latest_rtt
if latest_rtt >= min_rtt + ack_delay:
adjusted_rtt = latest_rtt - ack_delay
smoothed_rtt = 7/8 · smoothed_rtt + 1/8 · adjusted_rtt
Two safeguards matter on long paths. The subtraction only applies while the result stays at or
above min_rtt, the sender's floor, computed from locally observed times and never adjusted
for reported delay ([RFC 9002 §5.2]). So a peer that misreports a huge ack_delay cannot drive the
estimate implausibly low. And after the handshake is confirmed, the sender caps the delay it will
honour at the peer's advertised max_ack_delay (default 25 ms, [RFC 9000 §18.2]); the peer
"promises to never intentionally delay acknowledgments... by more than the indicated value," and
any excess "accrues to the RTT estimate" ([RFC 9000 §13.2.1]). Get this wrong and the smoothed RTT
inflates, which (because it feeds the PTO) makes every subsequent recovery slower.
The PTO: recovery latency that grows with RTT #
When nothing is acknowledged (the tail of a flight is lost, or an ACK is lost), there is no threshold to fire, and recovery falls to the Probe Timeout ([RFC 9002 §6.2]):
PTO = smoothed_rtt + max(4 · rttvar, kGranularity) + max_ack_delay
The PTO is built from the RTT estimate, so it is already long on a long path. Worse, each time it expires without progress the backoff doubles it ([RFC 9002 §6.2.1]), so "connection recovery latency increases exponentially as packets continue to be dropped" ([RFC 9002 §6.2.4]). A PTO does not mark packets lost or collapse the congestion window ([RFC 9002 §6.2, §4.7]); it sends one or two ack-eliciting probe packets to elicit an ACK and get the connection moving again. On a 200 ms path a single lost tail packet already costs a ~450 ms PTO before the first probe. A second loss costs ~900 ms. This is why tail loss is disproportionately painful at high RTT, and why keeping the flight filled (so a loss is detected by threshold, not by timeout) is a latency strategy in itself.
Worked example: a reordered packet on a satellite link #
Follow Figure 8.2-1 on a 200 ms path. The sender sends packets 10–13; the network delays 11 onto a
slower route. The receiver acknowledges 10, 12, and 13, reporting a 20 ms ACK delay. On the sender,
11 is now 3 packets behind the largest acknowledged (13), so the packet threshold declares it
lost and the sender retransmits, but 11 was only reordered and arrives moments later. The
retransmit was spurious: 200 ms of bandwidth and a congestion-window cut, spent because the path
reorders by more than 3. Meanwhile the 20 ms ack_delay is subtracted from the RTT sample (staying
above min_rtt), keeping the estimate honest. Had the receiver simply gone silent instead, the
sender would have waited a full PTO (smoothed_rtt + 4·rttvar + max_ack_delay, ~450 ms and
doubling) before probing.
min_rtt is the anchor that makes all of this robust. It is tracked from locally observed
send/receive times only, never adjusted for the peer's reported ack_delay ([RFC 9002 §5.2]), so it
is a trustworthy lower bound: the ACK-delay subtraction is floored at it, and loss-detection uses
it to reject implausibly small samples. On a path whose true RTT later increases, though, min_rtt
does not adapt upward on its own — it is reset on migration or after persistent congestion, so a
stale min_rtt after a path change is a real diagnostic to watch for (§8.5).
editorial On a long or lossy path, watch two trace signals.
First, the spurious-retransmission rate: if packets you retransmit are later acknowledged as
originally sent, the path reorders beyond kPacketThreshold and you are paying full-RTT penalties
for nothing. Some stacks expose a reordering-tolerance knob, but the honest fix is usually fewer,
larger, better-paced flights. Second, the PTO count and backoff: repeated PTOs with doubling
mean tail loss is dominating recovery; filling the congestion window so losses are detected by
threshold instead of timeout is worth more here than any parameter tweak. Both are measured
directly in §8.5.
Takeaways #
Loss, reordering, and ACK delay cost the same mechanism at any RTT but far more time on a long
path. Reordering beyond kPacketThreshold (3) triggers spurious retransmits that waste a full RTT;
reported ack_delay is subtracted from the RTT sample but floored at the locally observed
min_rtt and capped at max_ack_delay; and tail loss falls to a PTO that is already long and
doubles on each expiry. The response is to avoid needing recovery, through the latency-reduction
strategies of §8.3 and the concurrency design of §8.4.