A reliable protocol must account for six coupled problems: detecting loss and corruption, retransmitting without creating duplicates, ordering and reassembling fragments, bounding buffered state, adapting to path conditions, and authenticating every byte. These concerns interact, so a fix for one often destabilizes another. Loss detection without retransmission is useless; retransmission without duplicate suppression corrupts data; reassembly without memory bounds enables denial of service. The sections below explain the mechanisms, the numbers that constrain real implementations, and the edge cases that separate production protocols from textbook descriptions.
Loss and corruption detection mechanisms
Reliability starts with knowing what arrived and what did not. The two primary tools are checksums and sequence numbers, and they solve different problems. Checksums detect corruption in transit; sequence numbers detect absence.
Modern checksums are stronger than the 16-bit ones in older protocols. TCP and UDP use a 16-bit one's-complement checksum over a pseudo-header, which catches most random bit errors but offers weak protection against deliberate or structured corruption. QUIC uses a 16-bit header protection plus AEAD authentication at the transport layer, which means tampered packets fail authentication rather than merely failing a checksum. The practical consequence: a protocol relying only on a 16-bit checksum accepts roughly one undetected error per 65,536 corrupted packets, which is unacceptable on links where adversaries or faulty hardware exist.
Sequence numbers do the loss detection. TCP numbers bytes, not packets, so a single sequence number identifies exactly where in the stream a segment begins. This byte-oriented design means any gap in received sequence numbers signals loss, regardless of how packets were segmented. The receiver cannot distinguish a lost packet from a delayed one until a timeout fires, which is why loss detection is inherently probabilistic.
Plain language: checksums tell you a packet is damaged, sequence numbers tell you a packet is missing, and you need both.
Quantified context: windows, timers, and state costs
Reliability is bounded by memory and time, not just correctness. A protocol must size its state to the bandwidth-delay product of the path. On a 100 Mbps link with 100 ms round-trip time, the product is about 1.25 MB; a receiver window smaller than that caps throughput regardless of available bandwidth. TCP's classic 16-bit window field limited throughput on high-latency paths until window scaling was added, which multiplies the field by a negotiated factor up to 2^14.
Retransmission timers must adapt. A fixed timer either fires too early (wasting bandwidth on spurious retransmits) or too late (stalling the connection). TCP's retransmission timeout is computed from smoothed round-trip time estimates plus a variance term, with a minimum typically around 200 ms and exponential backoff on repeated failure. The number of retransmission attempts before declaring failure varies; TCP typically gives up after roughly 15 attempts spread over many minutes, while application-layer protocols often set tighter budgets.
Buffer sizing cuts both ways. Reassembly requires holding out-of-order data until gaps fill, but unbounded buffers become a memory-exhaustion vector. A receiver that allocates a full reassembly buffer per connection must multiply that cost by concurrent connections; 10,000 connections times 64 KB each exceeds 600 MB.
| Concern | Typical mechanism | Key numeric bound |
|---|---|---|
| Corruption | 16-bit checksum vs. AEAD tag | ~1 in 65,536 undetected with 16-bit |
| Loss detection | Sequence gaps + timeout | RTO floor ~200 ms |
| Ordering | Sequence numbers | 32-bit space wraps at 4 GB |
| Flow control | Advertised window | 16-bit field, scaled up to 2^14× |
| Reassembly | Fragment offsets | Offset field width caps max datagram |
| Duplicate suppression | Sequence dedup | Window-bounded state |
Reassembly and ordering edge cases
Reassembly is where reliability quietly becomes hard. IP fragmentation splits datagrams by offset, and reassembly fails if any fragment is lost, because IP has no retransmission of its own. A single dropped fragment discards the entire datagram, so protocols that fragment aggressively suffer amplified loss. This is why modern transports avoid IP fragmentation and segment at the transport layer instead.
Overlapping fragments are a security hazard. If two fragments claim the same offset with different contents, the receiver must choose, and implementations historically disagreed, enabling evasion of filtering devices. The correct approach is to reject overlaps or apply strict first-wins rules consistently.
Sequence number wraparound creates a subtler problem. A 32-bit sequence space reused too quickly lets old duplicate packets masquerade as new data. TCP mitigates this with timestamps and a maximum segment lifetime (commonly 2 minutes) that bounds how long a packet can persist in the network. Protocols that reassemble large messages must also bound total message size, because an attacker can send fragments with huge offsets to force memory allocation before any data arrives.
Counterintuitive detail: reliable delivery does not guarantee in-order delivery to the application. A protocol can guarantee every byte arrives exactly once while delivering them out of order, and some transports do exactly that, leaving ordering to a higher layer.
Misconceptions that break reliability
The most common misconception is that acknowledgments imply delivery. An ack means the receiver's stack accepted the data, not that the application processed it. Crash after ack but before application commit loses data despite a "reliable" transport.
Another is that retransmission is free. Every spurious retransmit consumes bandwidth and can worsen congestion, which is why congestion control and reliability must be co-designed. A protocol that retransmits aggressively on a congested path makes congestion worse.
A third is that bigger windows always help. Flow-control windows larger than the bandwidth-delay product waste memory; windows smaller than it cap throughput. The window must match the path.
Red flags to watch:
Checksums shorter than 32 bits on adversarial paths Reassembly buffers with no total-size cap Retransmission timers that never back off No maximum segment lifetime, allowing stale duplicates Fragment overlap handled inconsistently across implementations Acknowledgments treated as durable commits
Practical actions and thresholds
Start by sizing state to the path. Measure the bandwidth-delay product and set windows at least that large, then cap total per-connection memory and enforce it. Reject fragments with offsets beyond a configured maximum before allocating buffers.
Set retransmission timeouts from measured round-trip time, with a floor that prevents premature retransmission on low-latency paths and exponential backoff after repeated loss. Bound total retransmission attempts and surface failure to the application promptly.
Adopt strong integrity checks where adversaries exist. Prefer AEAD-style authentication over weak checksums, because a 16-bit checksum is a correctness check, not a security control. Enforce a maximum segment lifetime and use timestamps or nonce spaces to reject stale duplicates.
Plain language: match your windows to the pipe, cap your buffers, back off on retransmits, and authenticate everything.
Limitations and what protocols cannot promise
Reliability has hard limits. No transport layer can guarantee delivery if the receiver crashes after acknowledging, if storage fails below the protocol, or if the path is permanently partitioned. End-to-end reliability requires durable commitments at the application layer, typically through write-ahead logging or idempotent operations with explicit acknowledgment of persistence.
Congestion control interacts with reliability in ways no single setting fixes. Aggressive retransmission improves delivery probability on lossy-but-uncongested links and harms throughput on congested ones. Protocols must adapt rather than assume.
Finally, the thresholds above are engineering conventions, not physical laws. The ~200 ms timeout floor, the 2-minute segment lifetime, and window scaling limits reflect decades of deployment experience, and they vary by implementation and operating system. Treat them as starting points to measure against your own path, not as universal constants.