Field notes on things that run themselves

Issue No. 54 · · ~5 min read

The Limit Is Never Known, Only Crossed

Right now, somewhere between your phone and whatever server it’s talking to, a connection is deliberately trying to go too fast. That isn’t a bug. An ordinary internet connection has no way of knowing in advance how much of the network it’s allowed to use — no map, no dashboard, no office it can call and ask. So it finds out the only way it can: by speeding up until something gives, backing off, and immediately starting to speed up again. It has been doing this, in one form or another, for nearly forty years, and it is doing it again right now, underneath whatever you’re reading this on.

It wasn’t built to behave this way from the start. In the internet’s first decade, a sender with data to move simply sent as much as the receiver said it could hold, as fast as it could send it. That worked fine as long as the network had room to spare. It did not survive success. As more machines came online through the 1980s, routers began doing something unglamorous and, it turned out, catastrophic: when a queue of waiting packets filled up, they silently dropped whatever didn’t fit. TCP, doing exactly what it was designed to do, treated a missing packet as a delivery failure and sent it again — adding one more packet to a link that had just finished proving it couldn’t handle the packets it already had.

In October of 1986, that loop caught up with the young internet. Van Jacobson, an engineer at Lawrence Berkeley Laboratory, watched the data rate between two sites four hundred yards apart, linked by just two hops, collapse from 32,000 bits per second to 40. Not a slowdown — a thousand-fold crash, on a connection short enough to walk in under five minutes. The retransmissions weren’t curing the congestion. They were the congestion.

Jacobson, working with Michael Karels, spent the next two years building a fix, published in 1988 and folded that same year into a widely used release of Berkeley Unix. The core idea is almost embarrassingly simple once you see it. Every sender keeps a number called its congestion window — a live, private estimate of how much data the network can carry for it right now — and adjusts that number by two rules with very different temperaments. When everything arrives cleanly, the window creeps up by about one packet’s worth every round trip: patient, linear, cautious. The instant a packet goes missing, the window doesn’t ease down — it is cut in half immediately. The pairing has a name, additive increase, multiplicative decrease (engineers just say AIMD), and it isn’t a slogan tacked onto the algorithm afterward. It is the algorithm.

The asymmetry is the whole point. Climbing slowly costs, at worst, a little idle capacity. Overshooting costs a pile of dropped packets that then get resent — the exact mistake that caused the 1986 collapse, replayed in miniature every time it happens. Getting out of trouble fast matters more than finding the ceiling fast, so the rule is built to punish overshoot far harder than it punishes caution.

Left alone, a single connection’s window traces what engineers actually call, on the page, a sawtooth: climb, climb, climb, drop by half, climb again — for as long as the connection lasts, never settling on a number and staying there. (New connections get a faster on-ramp, confusingly named slow start, which doubles the window every round trip until it’s in the right neighborhood — “slow” only next to the old habit of dumping an entire window on the network at once.) There is no version of this algorithm that finds the right speed and holds it. Finding the edge, and briefly being past it, is not a flaw in the design. It is the design.

Here is the part that still catches people off guard. No connection knows how many other connections are sharing its link. Nothing is coordinating them; there is no scheduler in the middle handing out shares. Each one is purely self-interested, reacting only to its own gains and its own losses. And yet in 1989, Dah-Ming Chiu and Raj Jain proved something close to remarkable about this exact pairing of rules: climb-additively, fall-by-half isn’t just one reasonable way to divide a shared link among strangers who can’t see each other — among linear rules, it’s the only shape that’s mathematically guaranteed to converge on a fair, efficient split, no matter where every connection happened to start. Tune the selfishness with the right asymmetry, and it adds up to something like justice, with nobody in charge of making it so.

Real traffic is messier than that proof’s tidy assumptions. Connections have different round trips, arrive and leave at different moments, and increasingly run newer variants — Linux’s default, CUBIC, swaps the straight-line climb for a curve that goes cautious near a recent trouble spot and bolder once it’s past it, while other approaches watch for the earliest creep of delay instead of waiting for an outright loss. So the fairness in practice is closer to a rough, ongoing negotiation than an exact split. But the underlying instinct — cut your losses hard, rebuild your gains slowly — is still under almost everything you do online, running at the scale of billions of connections doing it at once, all day, every day.

There’s no filing cabinet anywhere holding the internet’s true capacity, and there doesn’t need to be. It’s rediscovered on purpose, by small, repeated failure — a system that stays honest about its own limits only by agreeing, forever, to keep testing them.

One loop I’m watching

Next: an ordinary running program, minting small objects by the thousand every second, almost all of which are already garbage the instant after they’re used. Left alone, that debris would eventually fill all available memory and stop the machine cold. Instead, a periodic housekeeper sweeps a small, fast nursery for the newly dead, promotes the rare long-lived survivors to a quieter shelf checked far less often, and reclaims the rest in bulk — betting, correctly, almost every time, that whatever a program just made, it’s already finished with.

Tip: the ← and → arrow keys move between issues.

New to The Standing Wave? Start here →