A practical look at TCP autotuning
Linux has grown its own send and receive buffers for years, and most of the advice
about setting net.ipv4.tcp_rmem by hand is a decade out of date. Still,
autotuning is not magic, and understanding where it stops helps when throughput on a
long fat path quietly tops out.
What grows automatically
The receive buffer grows on its own: the kernel samples the connection's receive rate and expands the window up to the maximum you allow. Sending is the same story. So for ordinary connections you rarely need to touch anything — the defaults scale to a few megabytes.
sysctl net.ipv4.tcp_rmem net.ipv4.tcp_wmem
# rmem = min default max
# wmem = min default max
Where it gives up
Autotuning bounds the window by what it has seen, which means it is slow to react to a path that suddenly opens up. On a link with a large bandwidth-delay product, a connection that stalls early can stay conservative for a long time. Raising the maximum is usually the useful knob; the minimum almost never matters.
The two settings that pay off
- tcp_mtu_probing — when a broken middlebox black-holes large packets, this lets the kernel find a working segment size instead of stalling.
- tcp_congestion_control — on lossy long-haul paths, a loss-tolerant algorithm often beats the default more than any buffer change.
sysctl net.ipv4.tcp_mtu_probing=1
sysctl net.ipv4.tcp_congestion_control=bbr # when available
Measure before and after
Buffer changes are easy to make and hard to attribute. Record throughput and retransmit rate for the same flow before and after, on the same path, at the same time of day. If both numbers do not move, revert — configuration you cannot explain is configuration you cannot debug later.