IL-0578 GMO Pepabo · 2020-06-26 (published)networking
Static content behind an HAProxy load balancer in an OpenStack Octavia amphora was delayed by tens of seconds
HAProxy ran in a VM inside an amphora of the OpenStack Octavia service, and the VM had only 2 GB of RAM. The Linux kernel sets the default net.ipv4.tcp_mem at boot from the amount of memory, so the TCP memory thresholds on this VM were low. The memory the kernel had allocated to TCP socket buffers went over these thresholds, the kernel entered TCP memory pressure mode and logged TCP out of memory, and performance dropped; the later investigation concluded that this caused the delays. An engineer tuned net.ipv4.tcp_mem with sysctl, which applies immediately to all sockets without restarting processes, and the delays stopped.
The investigation could not explain at first how this state delayed the content, so the author reproduced it in a Vagrant lab and read the kernel source. Above the pressure threshold the kernel limits send and receive buffer sizes and shrinks receive windows. Above the hard limit, the third value of net.ipv4.tcp_mem, it also drops newly received segments, blocks senders until memory is available, fails connect(2) with ENOBUFS, and resets sockets that are closed with data still in the send buffer, which is when it logs TCP out of memory.
- Severity
- –
- Scope
- Delivery of static content through the HAProxy load balancer was delayed by tens of seconds
- Users affected
- –
- Region
- –
- Time to detect
- –
- Time to resolve
- –
Symptoms
In a GMO Pepabo production setup, delivery of static content was delayed by tens of seconds. The static content was served by nginx on upstream hosts behind HAProxy, which ran as the HTTP load balancer.
During the response, an engineer found a host whose dmesg showed TCP: out of memory -- consider tuning tcp_mem. That host was the one running HAProxy.
Symptom High latency
Root cause
Root cause Capacity exhaustion
- Trigger
- –
Detection
–
Remediation
- Tuned net.ipv4.tcp_mem with sysctl on the HAProxy host, which ended the delays immediately
Action items
–
Lessons
On a VM with little RAM, the boot-time default of net.ipv4.tcp_mem can be low enough to push TCP into memory pressure. TCP out of memory is not the OOM killer, and net.ipv4.tcp_mem is a system-wide limit counted in pages, unlike the per-socket net.ipv4.tcp_rmem and net.ipv4.tcp_wmem counted in bytes. The values to watch are TCP mem in /proc/net/sockstat, press in /proc/net/protocols, and TCPMemoryPressures, TCPMemoryPressuresChrono and TCPAbortOnMemory in /proc/net/netstat.
Sources
References
Related cases
IL-0264Healthchecks.io requests slowed and timed out as HAProxy load balancers ran out of connection slots during a ping floodHealthchecks.io · 2025same root cause · shared HAProxy
IL-0558New PubNub instance types in FRA hit connectivity limits, and Pub/Sub, History and Presence saw intermittent errorsPubNub · 2025same root cause · shared Cloud load balancer
IL-0312Gadget's main Postgres did not start again after a restart to raise max_connections, and the platform went downGadget · 2024same root cause · shared Linux kernel
IL-0440Pods on Cybozu's Neco Kubernetes platform got frequent no such host and i/o timeout DNS errors from dropped packetsCybozu · 2024same root cause · shared Linux kernel
IL-0176Prometheus in a 235-node Kubernetes cluster crash-looped because over two million series exhausted host memory and the kernel OOM killer chose it first, as Burstable QoS gave it oom_score_adj 999LINE · 2020same root cause · shared Linux kernel
IL-0013The conntrack table filled up on downsized GKE nodes and a high-traffic aggregation proxy saw climbing connection resetsloveholidays · 2020same root cause · shared HAProxy
IL-0064CPU-heavy pods packed onto one Google Cloud node drove it to kernel panics, and the crash moved from node to node until the site was downMoonlight · 2019same root cause · shared Linux kernel
IL-0472Node-to-pod traffic and DNS failed on Tinder's 605-node Flannel cluster when every node's ARP cache passed gc_thresh3Tinder · 2019same root cause · shared Linux kernel
IL-0333A downsized RDS PostgreSQL database maxed out its CPU at US peak and failing ELB health checks took buildkite.com downBuildkite · 2016same root cause · shared Cloud load balancer
Check your cluster for this
For AI tools and scripts
- This case as JSON: https://incidentlib-api.benchlet.com/cases/IL-0578
- The cases most like it: https://incidentlib-api.benchlet.com/cases/IL-0578/similar
- MCP server (Streamable HTTP, no key):
https://incidentlib-mcp.benchlet.com/mcp
The API needs no key. The MCP server offers search_incidents, get_incident, list_incidents, get_topic and vocab; both are explained on API and MCP.