Sequence Numbers

Cut a stream into pieces, number each one where it starts, and the receiver can put them back whatever order they turn up in. That part is obvious. The part that is not is that the number is finite: it runs out and starts again, and at that moment the question which of two segments came first can no longer be answered by asking which number is smaller. The fix is not a bigger number. It is arithmetic on a circle, and a window narrow enough that the answer is never ambiguous.

The stream is in order and nothing underneath it is

1 A stream cut into segments, each one numbered where it starts

A stream cut into segments, each numbered where it starts in the stream.

0

seqcarries
0the␣
4quic
8k␣br
12own␣
16fox␣
20jump
24s␣ov
28er␣t
32he␣l
36azy␣
40dog

11 segments of 4 bytes, numbered from 0. It does not wrap: the last number is 40.

2 Deliver them in the wrong order and reassemble by number alone

Deliver them in the wrong order. The receiver never learns what order they arrived in — only what each one says about itself.

shuffle 7

arrived as
24, 16, 4, 36, 28, 8, 12, 20, …
reassembled
“the quick brown fox jumps over the lazy dog”
same as the stream
yes

Delivered in that order and reassembled from the numbers alone, the stream is byte-for-byte what was sent.

3 Run the number past its maximum and watch a comparison on a line fail

Push the numbering past its maximum and ask which came first. On a line, the answer is wrong for a quarter of all pairs.

numbers in the space
256
ordered pairs
65,280
where a < b is wrong
16,256 (24.9 per cent)
genuinely ambiguous
256 (exactly 128 apart)

Over every ordered pair of numbers in the space, the two comparisons disagree 16,256 times. That is not an edge case: it is 24.9 per cent of all pairs, and every one of them is a moment where a receiver would put a segment in the wrong place.

4 Compare on a circle instead, and the window that keeps it unambiguous

So compare on the circle instead: a is before b when the forward distance is less than half the space, and nothing is claimed at exactly half.

aba < bon the circleforward
1020beforebefore10
2504afterbefore10
4250beforeafter246
200100afterafter156
0128beforeneither128
1280afterneither128

2 of these 6 ordered pairs are judged differently by the two comparisons, and 2 are refused by the circle entirely: 128 apart is the same distance forward and backward, so both directions of that one pair get no answer.

These ran in this browser when the page loaded. Each claim, whether it held, and the number behind it.

Each claim, whether it held, and the values behind it
claimheldmeasured
800 scrambled deliveries reassemble to the same text, including four start points that wrapyesorder of arrival is not information
on 16,256 of 65,280 ordered pairs, a < b gives the wrong answeryesthat is 24.9 per cent of them, and every one is a real reordering bug on a real wrap
and 256 pairs are exactly half the space apart, where neither answer is rightyesthe comparison returns nothing for those rather than choosing, which is why a window smaller than half the space is required
254 comes before 2 on the circle and after it on the lineyesfour apart forward, 252 apart backward

What is real here, and what is not

Eight bits, not thirty-two, so the wrap is reachable

TCP numbers bytes in a thirty-two bit space, which at a gigabit takes about half a minute to wrap and is why the protocol has timestamps as well. This page uses eight bits so the wrap happens while you watch. Every statement about the arithmetic holds identically at either width; only the waiting is different.

This is the numbering, not TCP

There is no handshake here, no window advertisement, no retransmission, no congestion control and no state machine. Segments are never lost and never duplicated, which are the two things the numbering exists to survive. What the page models is the comparison, because that is the part that stops being obvious when the counter wraps.

Half the space is genuinely ambiguous, and refusing is a choice this page made

When two numbers are exactly half the space apart, neither is before the other in any useful sense: the forward distance and the backward distance are equal. This page returns nothing for those pairs rather than picking one. That is a decision, not a rule inherited from the standard, and an earlier version of this entry said otherwise. RFC 1982 leaves the case undefined and is explicit about what that permits: implementations are “free to return either result, or to flag an error, and users must take care not to depend on any particular outcome. Usually this will mean avoiding allowing those particular pairs of numbers to co-exist.” Free to return either result, so an implementation that guesses is conforming and this one is stricter than it has to be. The entry that stood here until 2026-08-22 credited the RFC with mandating a receiver window smaller than half the sequence space. The archived RFC contains no occurrence of the word window, or half, or MUST; the window constraint is real and belongs to TCP rather than to this document. An outside reader caught the attribution.

Sources