
The HTTP/2 Bugs Hiding in Plain Sight
transcript
show notes
Most develpors skip release notes. You update a library, the tests pass, you deploy, and everything seems fine. Later, someone spots that 0.025% of requests are failing; not enough to set off alarms, but too steady to ignore. This is what happens with the HTTP/2 upgrade you might not have noticed. Undici 8 and Node 26 now automatically use HTTP/2 if the server prefers it, so if your internal load balancer advertises HTTP/2, you’ve switched over without changing any code.
In this episode of The Node (and more) Banter, Luca Maraschi and Matteo Collina talk about the HTTP/2 bugs that showed up when real users started running into this new default. There were two bugs in Undici and one in HAProxy's Edge Ingress Controller. All of them were quiet, hard to reproduce, and shared a common cause: a GOAWAY packet that should have triggered a transparent retry was treated as an error, and a race condition in Undici's pool was closing active connections it thought were idle.
In this episode, we cover:
✅ How ALPN protocol negotiation works, and why updating Undici quietly shifted internal traffic to HTTP/2 without anyone noticing
✅ The GOAWAY bug: why Undici sent a server's graceful reconnect signal back to the user as an error instead of handling it smoothly as the RFC requires
✅ The race condition in Undici's pool and client counters, and how in-flight requests were dropped when the pool closed a connection it thought was idle
✅ The HAProxy bug that made things worse, and why a protocol that has existed for years still causes problems in production infrastructure
The takeaway?
HTTP/2 is a powerful protocol with features like multiplexed streams, no head-of-line blocking at the application layer, and better resource use at the kernel level. But in a private Kubernetes network with low latency and no packet loss, the benefits are not as clear. If your infrastructure upgrades in the background, you need to find out what breaks before your error rate goes up.