curl 8.16.0 Turbocharges Connection Racing with Parallel Happy Eyeballs v3-Inspired Algorithm
Share this article
When Daniel Stenberg first implemented Happy Eyeballs (RFC 6555) in curl over a decade ago, the internet landscape looked radically different. The algorithm—which prioritizes IPv6 connections while racing IPv4 alternatives—solved a critical problem: avoiding IPv6 connection delays without abandoning IPv6 adoption. But as QUIC, HTTP/3, and multi-address environments emerged, cracks appeared in this elegant solution. Today, curl 8.16.0 responds with its most aggressive connection optimization yet: parallel multi-address racing.
The Eyeballs Evolution
RFC 6555's original brilliance lay in its simplicity:
"Give the IPv6 attempt priority, then with a delay start a separate IPv4 connection in parallel; use whichever succeeds first."
This "connection racing" became ubiquitous. The 2017 RFC 8305 (Happy Eyeballs v2) pushed further, urging clients to initiate connections during DNS resolution rather than after—a challenge for portable libraries like libcurl due to POSIX API limitations.
QUIC's Game-Changing Complication
HTTP/3's dependency on QUIC introduced new hurdles. Unlike traditional TCP, QUIC requires prior knowledge (via alt-svc headers) before attempting connections—a deal-breaker for curl's single-shot transfers:
/* Traditional flow forced late QUIC discovery */
response = get("https://example.com");
if (response.headers.alt-svc)
then_attempt_quic(); // Often too late!
curl's answer? Treat QUIC as a separate transport layer competitor. The new hierarchy:
1. QUIC over IPv6
2. QUIC over IPv4
3. TCP over IPv6
4. TCP over IPv4
Parallel Revolution: 200ms Intervals
curl 8.16.0's breakthrough comes from Stefan Eissing's work: aggressively parallelizing connections when responses lag. The algorithm now works like a Formula 1 starting grid:
- T=0ms: First IPv6 connect attempt starts
- T=200ms: First IPv4 attempt launches in parallel
- T=400ms: If no success, second IPv6 attempt joins the race
- T=600ms: Still blocked? Second IPv4 attempt fires
Caption: Connection attempts escalate every 200ms until success (Image: Daniel Stenberg)
QUIC + TCP: Double Races
When both QUIC and TCP are viable, curl runs two simultaneous races after 200ms:
| Time (ms) | QUIC Actions | TCP Actions |
|---|---|---|
| 0 | Start IPv6 connect | – |
| 200 | Start IPv4 connect | Start IPv6 connect |
| 400 | Start 2nd IPv6 | Start IPv4 connect |
| 600 | Start 2nd IPv4 | Start 2nd IPv6 |
In worst-case scenarios, nine connection attempts could be racing by 800ms. The 200ms threshold is configurable via --happy-eyeballs-timeout-ms.
Why This Matters
This isn't academic optimization. For global services:
- Latency-sensitive apps (video conferencing, gaming) gain critical milliseconds
- Unreliable networks failover faster during regional outages
- IPv6 adoption accelerates by eliminating "wait-and-see" penalties
As IETF finalizes Happy Eyeballs v3 (incorporating HTTPS-RR DNS records), curl's implementation provides battle-tested insights. What began as an IPv6 transition tool now orchestrates multi-transport, multi-address chaos—proving that sometimes, the fastest way to connect is to try everything, all at once.
Source: Daniel Stenberg's blog