1. Library
  2. Computer Networks
  3. Tcp and Udp
  4. Tcp

Updated 9 hours ago

In 1984, John Nagle watched the early Internet drown in tiny packets. A user typing in a Telnet session would generate one packet per keystroke—a single byte of data wrapped in 58 bytes of headers. The network was spending 98% of its effort on envelopes and 2% on letters.

Nagle's solution was elegant: hold small writes in a buffer until either the receiver acknowledges previous data, or enough new data accumulates to fill a proper packet. The algorithm transformed chatty applications into efficient ones without changing a line of application code. It reduced packet rates by up to 90%.

That was forty years ago. Networks now have bandwidth to spare, but users have grown intolerant of latency. The optimization that saved the early Internet now actively fights against what modern applications need. Understanding when Nagle's algorithm helps versus hurts is the difference between a responsive application and one that feels inexplicably sluggish.

How Nagle's Algorithm Works

Every TCP packet carries overhead: 20 bytes of IP header, 20 bytes of TCP header, 18 bytes of Ethernet framing. When an application sends a single byte, that byte travels in a 58-byte packet—a 5,700% overhead ratio.

Nagle's algorithm implements a simple rule:

  • If the data is large enough to fill a maximum segment size (MSS) packet, send immediately
  • If there's no unacknowledged data in flight, send immediately
  • Otherwise, buffer the data until an ACK arrives or a full packet accumulates

The first write always goes out instantly. Subsequent small writes wait for the receiver to acknowledge what's already in flight. When the ACK arrives, everything buffered gets sent together.

This dynamic behavior adapts to network conditions. Fast networks with quick ACKs experience minimal buffering. Slow networks with delayed ACKs trigger more aggressive batching—exactly when bandwidth matters most.

The Problem It Solved

The 1980s Internet operated on a bandwidth budget that seems quaint today. Applications like Telnet generated catastrophic waste without knowing it. Developers wrote code that made sense from an application perspective—send data when it's ready—without understanding the network-level implications.

Each keystroke in a remote terminal session became its own packet. A user typing "ls -la" might generate eight packets where one would suffice. Multiply by thousands of users, and the network spent most of its capacity on headers.

Nagle's algorithm fixed this transparently. No application changes required. The TCP stack simply started batching small writes automatically, and packet rates dropped dramatically. For bandwidth-constrained networks, this was transformative.

Disabling It with TCP_NODELAY

The TCP_NODELAY socket option tells TCP to abandon Nagle's algorithm and transmit every write immediately, regardless of size. More packets, more overhead, but instant delivery.

int flag = 1;
setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));

Once set, TCP_NODELAY remains active for the socket's lifetime. There's no automatic re-enabling, no conditional behavior. Every write becomes a packet.

When to Disable It

Real-time gaming is the canonical case. Player inputs must reach the server now, not after a round-trip delay. Players notice latency above 30-50ms. Waiting for an ACK before sending the next input makes games feel sluggish and unresponsive.

Remote desktop protocols need immediate mouse position updates. Any batching delay makes the cursor lag behind the user's hand—a jarring disconnect that makes remote systems feel broken.

Financial trading operates on microsecond timescales. Nagle's delay isn't a nuisance; it's a competitive disadvantage measured in money.

SSH and terminal emulators benefit from TCP_NODELAY for interactive sessions. Modern networks have bandwidth to spare, so the efficiency gains are negligible, but the latency reduction makes remote shells feel local.

HTTP servers often enable TCP_NODELAY for dynamic content. When streaming responses incrementally, immediate transmission beats batching for user experience.

Bulk data transfers are the exception. File downloads, backups, and synchronization should keep Nagle's algorithm enabled. When you're moving megabytes, full packets matter and latency doesn't.

The Delayed ACK Problem

Nagle's algorithm has an unfortunate interaction with another TCP optimization: delayed acknowledgments. Receivers don't ACK every packet immediately—they wait up to 200ms hoping to piggyback the ACK on outgoing data or to acknowledge multiple packets together.

When both optimizations are active, they create a standoff. The sender waits for an ACK before sending the next small packet. The receiver delays sending that ACK hoping to piggyback it on response data. Both are being polite. Both are making things worse.

This hits request-response protocols especially hard. The client sends a small request. Nagle's algorithm holds any follow-up data waiting for an ACK. The receiver delays that ACK waiting to piggyback it on the response. But the response can't be generated until the request is complete. Everyone waits.

The fix is TCP_NODELAY on the client side. Some systems offer TCP_QUICKACK to disable delayed acknowledgments temporarily, but TCP_NODELAY is more commonly used and understood.

Modern Defaults

The calculus has inverted since 1984. Bandwidth is cheap. Latency is expensive. User expectations have shifted from "it works" to "it works instantly."

For anything interactive, disable Nagle's algorithm. The bandwidth overhead is noise on modern networks. The latency improvement is perceptible.

For bulk transfers, keep it enabled. Efficiency still matters when moving large data, and there's no user waiting on each packet.

For HTTP/2 and HTTP/3, the question is moot. These protocols implement their own multiplexing and prioritization, making TCP-level batching redundant.

For new protocols, design packet efficiency into the application layer. Modern protocols batch messages where they understand semantic boundaries—a smarter approach than TCP's blind byte-stream coalescing.

Test with realistic latency. Nagle's behavior depends heavily on round-trip times. What works on localhost will behave differently across the Internet.

Frequently Asked Questions About Nagle's Algorithm

Was this page helpful?

😔
🤨
😃
Nagle's Algorithm and TCP_NODELAY • Library • Connected