← Back to context

Comment by drfignewton

1 day ago

I swear, it seems like I’ve seen some variation of this 50 times on HN in the past 15 years.

The core issue with Nagle’s algorithm (TCP_NODELAY off) is its interaction with TCP Delayed ACK. Nagle prevents sending small packets if an ACK is outstanding, while the receiver delays that ACK to piggyback it on a response. When both are active, you get a 200ms "deadlock" where the sender waits for an ACK and the receiver waits for more data. This is catastrophic for latency-sensitive applications like gaming, SSH, or high-frequency RPCs.

In modern times, the bandwidth saved by Nagle is rarely worth the latency cost. You should almost always set TCP_NODELAY = 1 for any interactive or request-response protocol. The "problem" only shifts to the application layer: if you disable Nagle and then perform many small write() calls (like writing a single byte at a time), you will flood the network with tiny, inefficient packets.

Proper usage means disabling Nagle at the socket level but managing your own buffering in user-space. Use a buffered writer to assemble a logical message into a single memory buffer, then send it with one system call. This ensures your data is dispatched immediately without the overhead of thousands of tiny headers. Check the Linux tcp(7) man page for implementation details; it is the definitive reference for these behaviors.

> In modern times, the bandwidth saved by Nagle is rarely worth the latency cost.

I actually took some packet dumps and did the math on this once, assuming any >=2 non-mtu-sized segments from the same flow within 10ms could have been combined (pretty conservative imo). The extra bandwidth cost of NODELAY amounted to just over 0.1% of the total AWS bandwidth bill, which, while negligible, was more than I expected.

> Proper usage means disabling Nagle at the socket level but managing your own buffering in user-space.

Honestly, if you're writing a (cough) typical webservice that just serializes an object to JSON, you've pretty much done that. Nagle just slows that situation down, and TCP_NODELAY should always be enabled in that situation. (Granted, if you're using newer HTTP (3? SPDY?) you probably aren't even on TCP and don't even need to bother.)

It's only when sending large payloads that you might have to think about buffering.