The README Said Unordered

Written later and filed to this date, as part of filling in every day of the year.

The first commit landed at 18:22 on a Sunday in April and the seventeenth, a cleanup, at 22:07. Between them a repository called pong went from empty to a playable browser Pong with live one-on-one multiplayer, touch controls, a single-player opponent, a ball that changes colour with speed, and a README describing a network design the code had already given up.

What it was for

The idea is in the README’s first line: a Pong clone with multiplayer “over WebRTC in an unreliable + unordered data channel mode (UDP-like)”. Browsers do not give you UDP. A WebRTC data channel, by default, behaves like TCP: everything arrives, in order, retransmitted until it does. For a fast game that is the wrong contract. A paddle position from forty milliseconds ago is worthless once a newer one exists, and a channel that insists on delivering the old one first holds the new one behind it. So you open the channel with two flags, ordered: false and maxRetransmits: 0. Lost packets stay lost. Late packets are not waited for. The README prints the two flags in a code block and lists what they buy: no head-of-line blocking, no stale data after newer data.

The rest of the design is small and sound. The host runs the simulation and is the authority; the guest sends inputs the moment they change and receives a full state snapshot every three frames. Physics steps on a fixed timestep at sixty hertz with an accumulator, so both ends advance the same way. Players find each other through a tiny worker with a durable object as the meeting room, and once the offer and answer have crossed, the server drops out and the two browsers talk directly.

What the code did

Open the file that creates the channel, as it stood at 22:07, and the options object reads ordered: true. The comment beside it: keep packets ordered for consistent game state.

Retransmits got split three ways. On a phone, three retries, for reliability. On a desktop, none, to keep latency down. Between two tabs on one machine, no limit at all, because, the comment explains, for local testing reliability matters more than latency.

So by the end of the evening the channel the README calls UDP-like was ordered everywhere and retransmitting on two of the three kinds of connection the code could tell apart. The flags that gave the project its reason to exist had been bargained away, and the README, written at 21:59, still described the intention from 18:22.

The log says roughly how. At 19:25, an hour in: “Fix WebRTC connections for local testing and improve connection reliability”, two files, two hundred and forty-nine lines added. That is the commit where the evening’s connection trouble met the design, and the design lost. Unreliable, unordered delivery is a promise you make to your own game loop: that it can cope with gaps, and with stale frames arriving out of turn. The loop could not yet, the connection was flaky between two tabs on one laptop, and “consistent game state” is what you reach for at 19:25 when the ball keeps jumping.

What it taught

Two things, both more about documents than about packets.

The first is that a README written at the end of a build describes the idea, not the artifact. Nobody lied. The author knew what the project was about and wrote that down. The code knew what the evening had been like. A reader a year on who trusts the README will be debugging a design that never shipped, and a reader who trusts only the code will not know there was a design at all. The honest unit is the pair, and the gap between them is where the interesting decision lives.

The second is about which decisions get bargained away first. Not the cheap ones. The flags were cheap to set and expensive to live with, because everything downstream of them (dead reckoning on the guest, discarding stale frames, tolerating gaps) is work that only exists while the flags stay set. Turn them off and that work never gets scheduled, and the project quietly becomes an ordinary reliable-channel Pong with an unusual README.

Nothing has been committed to the repository since that night: seventeen commits in under four hours, then silence. I keep it as the clearest small example I have of a pattern that shows up at every scale: the premise is in the docs, the compromise is in the config, and the compromise was made at 19:25 for a reason nobody wrote down.


← all writing