384 Handshakes Was the Bug
Go back to where Delta began. Loomis needed 384 Eagle thumbnails from another Mac, and each one was fetched by a fresh SSH session: a new TCP connection, a new key exchange, a new login, for a few kilobytes of image. sshd treats a crowd of half-finished logins as an attack and starts dropping them (MaxStartups), so 152 of the 384 failed, and the ones that succeeded had a median of 3.8 seconds. The thumbnails were never the expensive part. The connections were.
Through Delta the same grid finished with zero failures in 1.94 seconds cold, with a median of 0.19 seconds and a p99 of 0.30, and warm runs were all 304s with no new bytes. The cache in front (track 5) explains the warm runs; the cold run is mostly this lesson: one pool of persistent connections per road, so a burst of 384 requests rides a handful of TCP connections instead of 384 handshakes.
The Pool
PeerClient keeps idle HTTP/1.1 connections keyed by everything that makes a connection what it is: host, port, whether it is TLS, and the pinned fingerprint. A connection made for the Thunderbolt address is never handed to a request for the LAN address, and a TLS connection pinned to one certificate is never reused after the peer published another. After a request finishes reading its body cleanly, the connection goes back into its pool. Up to 16 idle connections are kept per route; anything beyond that is closed.
The pool also has an expiry, and the number is chosen against the other end. The peer's gateway idles a keep-alive out after 75 seconds; the client throws away anything idle for more than 50. The gap matters: if both used 75, the client would sometimes pick a connection at the very moment the server closed it, and the request would die in the socket. Retiring connections earlier than the server does makes that race rare.
Rare is not never. A pooled connection can still have died while idle (the peer restarted, a cable was swapped). When a reused connection fails in the way a dead socket fails (the remote end disconnected, a reset, a broken pipe) and the request is idempotent, Delta closes that connection, drops all its idle siblings on the same road (they almost certainly died with it), and tries again. With the road's pool now empty, that second try opens a fresh connection, so in practice the silent retry happens once; the loop's ceiling of three attempts is reached only if another request hands a connection back to the pool in between. This retry is silent, and that is correct: the request never reached the peer, so nothing happened that anyone needs to hear about. A fresh connection that fails the same way is a real error and is named as one.
Two small settings complete the picture. Every new connection turns on TCP_NODELAY, so small requests are not held back by Nagle's algorithm waiting to fill a packet. And every response is read with Accept-Encoding: identity, so the byte count on the wire is the byte count of the file.
Every Failure Names Its Phase and Its Road
A request can fail in four places, and Delta's error says which, on which route, after how long:
| Phase | What the error says |
|---|---|
| Connect | connect to … via thunderbolt (… :5201 on bridge0) timed out after 2.0 s |
| First byte | first byte from … for GET … via lan did not arrive within 30 s |
| Stall | … stopped sending for 30 s at 1.2 of 4.0 MiB via tailnet |
| Cut | … closed the connection mid-body at 10 of 100 bytes via lan |
These messages travel. An error crosses the wire as {"error", "detail", "status"} and is rebuilt on the other side with the same class (Unavailable is 503, Timeout is 504), so an app three hops away reads the sentence the failing hop wrote, not a bare "502".
The Silent Short Read
The last row of that table exists because of a trap in Python's standard library. http.client's read() with no argument raises IncompleteRead if the connection ends before Content-Length bytes arrived. But read(n) with a size, which is what any program streaming a large body uses, returns whatever arrived, short, without a word. A peer that died halfway through a 16 MiB chunk would hand the caller fewer bytes and a clean return.
So everything that reads from a peer in Delta goes through peer.Response. It counts every byte it hands out, and when the body ends it compares the count with Content-Length (a 304 and a HEAD carry no body and are exempt). Short means Unavailable: closed the connection mid-body at N of M: a named error, never a short answer. Run shortread.py below to watch the standard library return 10 bytes out of a promised 100 and raise nothing.