RFC 896
HISTORIC · IDEAS LIVE ONCongestion Control in IP/TCP Internetworks
John Nagle (Ford Aerospace) · January 1984 · original status: Unknown (pre-standards-track memo) · current status: Historic
obsoleted by: RFC 7805
Historic (RFC 7805). Half prophecy, half patch: it predicted congestion collapse four years before it happened (answered by slow start, today's RFC 5681), and its small-packet rule survives in every stack as 'the Nagle algorithm' (RFC 9293 §3.7.4, off-switch: TCP_NODELAY).
This module teaches BOTH the historical problem and today's rules
This document
- RFC 896 — 'Congestion collapse' (the prophecy)
- RFC 896 — 'The small-packet problem' and the inhibit-while-unacked rule (the Nagle algorithm)
- RFC 896 — 'The source quench problem' (obsolete: ICMP Source Quench deprecated by RFC 6633)
Where the current rules live
- RFC 9293 §3.7.4 — Nagle algorithm (SHOULD, with an application off-switch)
- RFC 1122 §4.2.3.4 — sender SWS avoidance incorporating Nagle
- RFC 5681 — the congestion-control machinery that answered the collapse prediction
Congestion & the Small-Packet Problem (Nagle)
New to these ideas? Switch to the beginner level for a from-zero concept primer.
The problem this document answered
A telnet keystroke costs 4000% overhead: 1 payload byte, 40 header bytes, plus the ACK coming back. Nagle's rule — while anything is unacknowledged, buffer small writes until the ACK returns or a full segment accumulates — batches exactly as aggressively as the network is slow. No timers, no configuration.
Historical context
RFC 896 (January 1984) is a field report from Ford Aerospace's congested networks. Historic status (RFC 7805) — yet the small-packet rule is in every stack as 'the Nagle algorithm', and the collapse analysis became the founding problem statement of congestion control. Its third topic, ICMP Source Quench, is fully retired (RFC 6633).
Current practice
Nagle is on by default everywhere (RFC 9293 §3.7.4, SHOULD) with a mandatory application off-switch (TCP_NODELAY). Latency-sensitive software — games, trading, many RPC frameworks — disables it deliberately and knowingly pays the tinygram tax.
Interactive laboratory
⌨️ Typing laboratory — every number below comes from a live engine run
Nagle and delayed ACK solve different problems (sender efficiency vs receiver ACK economy) — try Nagle ON + delayed ACK ON with a big RTT and watch them wait on each other.
Guided walkthroughs — coached, packet by packet
Auto-pausing checkpoints explain every key packet: why it was sent, what each side believes, and what must happen next. Start here, explore freely after.
🎓 congestion collapseAuto-pausing checkpoints explain every key packet: why it was sent, what each side believes, and what must happen next. Start here, explore freely after.
Watch it on the wire
Eight keystrokes typed into a remote session with Nagle disabled: one 41-byte-overhead packet per byte of typing.
The same eight keystrokes with Nagle enabled: the first byte goes immediately, the rest coalesce behind the outstanding ACK — self-clocked batching.
A slow link (60 B/ms), a 4-packet router queue, and a sender whose RTO (80 ms) is shorter than the queue-inflated RTT: premature retransmissions flood the queue with duplicates, drops multiply, and goodput falls while total traffic rises.
The identical slow, shallow-queued link — but with a conservative 1-second RTO. The burst tail still overflows the queue, yet every retry now answers a REAL loss: no spurious copies, no duplicates competing with live data.
Compare correct vs historic / naive behaviour
Eight keystrokes over a 40 ms RTT: one packet per keystroke (Nagle off) versus self-clocked coalescing (Nagle on).
⇄ Congestion collapse vs a patient timerThe same slow, shallow-queued link and the same 17.5 KB transfer — once with an RTO shorter than the queue-inflated RTT (premature retransmissions), once with a conservative timer.
Original RFC vs current standard
The small-segment rule
- Original behaviour
- RFC 896: inhibit new small segments while ANY data is unacknowledged — stated absolutely, no escape hatch.
- Current behaviour
- RFC 9293 §3.7.4: SHOULD implement, MUST allow the application to disable per connection.
- What changed
- A mandatory off-switch was added.
- Why it changed
- Interactive and request/response workloads legitimately prefer latency over efficiency — the X Window System fight made this famous.
📷 In a capture: Nagle on: bursts of coalesced writes released by returning ACKs. TCP_NODELAY: every write on the wire immediately, tiny or not.
Common misconceptions
- ✗“Nagle adds a fixed delay” — it adds NO timer; data waits only for the in-flight ACK, so on a fast LAN the wait is microseconds.
- ✗“Nagle and delayed ACK are the same feature” — sender-side batching vs receiver-side ACK economy; they solve different problems and can deadlock each other briefly.
- ✗“Disabling Nagle makes everything faster” — it trades bandwidth for latency; bulk transfers gain nothing and chatty apps flood the wire.
- ✗“Congestion collapse means total outage” — it's worse: the network stays busy at full load while delivering almost nothing useful.
Glossary terms used here
Knowledge check
1/3 · With Nagle enabled, keystroke 'a' left immediately but 'b','c','d' travelled together. What released them?
2/3 · Which workload is the textbook case for setting TCP_NODELAY (disabling Nagle)?
3/3 · A client does write(header); write(body); read(reply) and stalls ~200 ms per request. The classic explanation?