Frontend Labs
⋯

37. Tuning knobs on Linux (sysctl reference)

Apply with sysctl -w key=value (runtime) and persist in /etc/sysctl.d/99-net.conf. Measure before and after. Defaults are good for most hosts; tune deliberately for a known workload (WAN bulk transfer, high- connection-count edge proxy, low-latency RPC).

37.1 Core buffers & backlog

sysctl Typical default When to raise Notes
net.core.rmem_max / wmem_max 208 KB–4 MB WAN bulk transfer absolute cap for SO_RCVBUF/SO_SNDBUF and TCP autotune max
net.core.netdev_max_backlog 1000 10G+ NICs, softirq drops per-CPU queue between NIC and stack; raise to 5000–30000 if nstat shows netdev_backlog drops
net.core.somaxconn 4096 (older: 128) busy accept()ers must also pass a large backlog to listen()
net.core.default_qdisc fq_codel fq for BBR / pacing bufferbloat control

37.2 TCP memory & windows

sysctl Meaning
net.ipv4.tcp_rmem = min default max per-socket receive buffer autotuning bounds (bytes). Raise max to ~2×BDP for WAN.
net.ipv4.tcp_wmem = min default max per-socket send buffer autotuning bounds.
net.ipv4.tcp_mem = low pressure high (pages!) system-wide TCP memory limits in 4 KB pages. Under memory pressure the stack shrinks windows and prunes. Raise on hosts with millions of sockets.
net.ipv4.tcp_moderate_rcvbuf = 1 enable receive-buffer autotuning (keep on).
net.ipv4.tcp_window_scaling = 1 keep on always.
net.ipv4.tcp_adv_win_scale app-data vs window split of the rcvbuf.

37.3 Connection setup / teardown

sysctl Meaning
net.ipv4.tcp_max_syn_backlog SYN-queue size (half-open). Raise to 8192–65536 on public-facing servers.
net.ipv4.tcp_syncookies = 1 SYN-flood protection; keep on.
net.ipv4.tcp_syn_retries / tcp_synack_retries initial SYN / SYN-ACK retransmit count (~6/5 → ~127 s / ~31 s). Lower for faster failover.
net.ipv4.tcp_abort_on_overflow = 0 on accept-queue overflow, drop the ACK (client retries) rather than RST. Keep 0 unless you prefer fast failure.
net.ipv4.tcp_fin_timeout = 60 bounds FIN_WAIT_2.
net.ipv4.tcp_tw_reuse = 2 reuse TIME_WAIT for outbound connects when safe (timestamps). Set 1 on busy clients. Never tcp_tw_recycle (removed/broken).
net.ipv4.ip_local_port_range = 32768 60999 ephemeral source ports. Widen to 1024 65535 on heavy outbound-connection hosts.
net.ipv4.tcp_max_tw_buckets cap on TIME_WAIT sockets (excess are killed early).
net.ipv4.tcp_max_orphans cap on orphaned (no fd) sockets; DoS guard.

37.4 Reliability / recovery

sysctl Meaning
net.ipv4.tcp_sack / tcp_dsack = 1 keep on — essential on lossy/long paths.
net.ipv4.tcp_fack deprecated (RACK supersedes).
net.ipv4.tcp_recovery = 1 enable RACK-TLP loss detection (default on modern kernels).
net.ipv4.tcp_early_retrans early-retransmit / TLP behavior.
net.ipv4.tcp_frto = 2 spurious-RTO detection & undo.
net.ipv4.tcp_retries2 = 15 ~13–30 min before killing an established connection. Lower (e.g. 8 ≈ ~100 s) for faster failover clusters; or use TCP_USER_TIMEOUT per socket.
net.ipv4.tcp_slow_start_after_idle = 1 reset cwnd after an idle period. Set 0 for long-lived keep-alive connections / HTTP/2 origins to avoid re-ramping after every idle gap.
net.ipv4.tcp_notsent_lowat limit unsent bytes in the send buffer → lower latency for apps that write large buffers then want to react (e.g. adaptive video). Try 131072.

37.5 Congestion control / pacing / ECN

sysctl Meaning
net.ipv4.tcp_congestion_control cubic (default) / bbr / dctcp (DC only).
net.ipv4.tcp_available_congestion_control loaded modules.
net.core.default_qdisc = fq needed for BBR pacing (or fq_codel).
net.ipv4.tcp_ecn = 2 accept ECN if peer requests; 1 also actively requests it.
net.ipv4.tcp_pacing_ss_ratio / tcp_pacing_ca_ratio pacing aggressiveness in slow start / congestion avoidance.

37.6 Offloads, routing, misc

sysctl / tool Meaning
net.ipv4.tcp_mtu_probing = 1 (or 2) PLPMTUD: probe for MTU when a black hole is suspected — mitigates ICMP-filtered paths (Ch. 8). 2 with a set base MSS is aggressive.
net.ipv4.tcp_timestamps = 1 keep on (RTT accuracy + PAWS); 0 only if a middlebox mangles them.
net.ipv4.tcp_fastopen = 3 enable TFO client+server.
net.ipv4.ip_forward = 1 make the host a router.
net.ipv4.conf.all.rp_filter = 1/2 reverse-path filter: 1 strict (drops asymmetric), 2 loose (multi-homed hosts).
net.netfilter.nf_conntrack_max firewall state table size; raise on NAT gateways/LBs or new flows get dropped (nf_conntrack: table full).
net.ipv4.neigh.default.gc_thresh1/2/3 ARP/ND cache GC thresholds; raise on hosts with thousands of neighbors or you get neighbour table overflow.
fs.file-max, ulimit -n fd ceilings — a million connections needs a million fds.

37.7 A sample profile: WAN bulk-transfer host

# /etc/sysctl.d/99-wan-transfer.conf
net.core.rmem_max            = 268435456
net.core.wmem_max            = 268435456
net.ipv4.tcp_rmem            = 4096 131072 268435456
net.ipv4.tcp_wmem            = 4096 131072 268435456
net.ipv4.tcp_mem            = 786432 1048576 26777216
net.core.default_qdisc       = fq
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_mtu_probing     = 1
net.core.netdev_max_backlog  = 30000

37.8 A sample profile: high-connection-count edge proxy

net.core.somaxconn            = 65535
net.ipv4.tcp_max_syn_backlog  = 65535
net.ipv4.ip_local_port_range  = 1024 65535
net.ipv4.tcp_tw_reuse         = 1
net.ipv4.tcp_fin_timeout      = 15
net.ipv4.tcp_slow_start_after_idle = 0
net.netfilter.nf_conntrack_max = 2000000
fs.file-max                   = 3000000
# plus: ulimit -n 1048576 for the proxy process

37.9 War story

An SRE copied a "10 Gbit tuning" blog's sysctls onto every host in the fleet, including tiny 512 MB edge boxes. net.ipv4.tcp_mem was set to huge values and tcp_rmem max to 64 MB. Under a connection surge those boxes OOM-killed the proxy because a few thousand connections × tens of MB of window blew past RAM. Lesson: buffer maxima are per socket; on memory-constrained or high-fan-in hosts, keep tcp_rmem/wmem max modest and cap total with tcp_mem. Tune per role, not per blog post.

Try it yourself

sysctl -a --pattern 'net.(ipv4.tcp|core)'      # dump all current values
nstat -az                                       # the counters to watch before/after
watch -n1 'nstat -az | grep -E "ListenDrops|ListenOverflows|TCPBacklogDrop|PruneCalled|RcvPruned|OfoPruned|TW"'
cat /proc/net/sockstat                           # TCP mem pages in use vs tcp_mem

Generated from real-life-example.md · 8 Oct 2026 16:36