Happy Eyeballs: Dual-Stack Connection Racing
Understand the Happy Eyeballs algorithm (RFC 8305) that ensures fast connections on dual-stack networks by racing IPv6 and IPv4 simultaneously.
The Dual-Stack Problem
On a dual-stack network, your device has both IPv4 and IPv6 addresses. When connecting to a server that has both A and AAAA DNS records, which protocol should the client use?
Naive approaches fail:
- Always prefer IPv6 -- If IPv6 is broken (misconfigured firewall, tunnel timeout), the user waits 30+ seconds for the TCP timeout before falling back to IPv4.
- Always prefer IPv4 -- Defeats the purpose of deploying IPv6.
Enter Happy Eyeballs
Happy Eyeballs (RFC 8305, originally RFC 6555) solves this by racing connection attempts:
Time 0ms: Start DNS queries for AAAA and A records
Time 50ms: AAAA response arrives -> Start IPv6 TCP connect
Time 300ms: IPv6 connect not done yet -> Start IPv4 TCP connect (race!)
Time 350ms: IPv4 connects first -> Use IPv4, cancel IPv6 attempt
The key insight: start IPv6 first (to encourage adoption), but do not wait long before trying IPv4 as a backup.
The Algorithm (RFC 8305)
Step 1: DNS Resolution
Send AAAA and A queries simultaneously. Do not wait for one before starting the other.
Step 2: Sort Destination Addresses
Order the results by preference:
- IPv6 addresses first (prefer native IPv6)
- Interleave address families: IPv6, IPv4, IPv6, IPv4...
- Apply RFC 6724 source/destination address selection rules
Step 3: Connection Racing
Attempt 1: Connect to first address (IPv6)
Wait 250ms: If not connected, start Attempt 2 (IPv4)
Wait 250ms: If not connected, start Attempt 3 (next IPv6)
...continue until one succeeds or all fail
The connection attempt delay (250ms recommended) gives IPv6 a head start without causing noticeable delay if it fails.
Step 4: Use the Winner
Whichever connection completes first wins. Cancel all other pending attempts to conserve resources.
Why 250ms?
The delay is a tradeoff:
- Too short (50ms) -- IPv6 rarely gets a chance; always falls back to IPv4.
- Too long (2s) -- Users notice the delay when IPv6 is broken.
- 250ms -- Fast enough that users do not notice, long enough to give IPv6 a fair chance.
Some implementations (Chrome, Firefox) use adaptive delays based on historical success rates.
Implementation in Practice
All major browsers and operating systems implement Happy Eyeballs:
| Software | Version | Standard |
|---|---|---|
| Chrome | All modern | RFC 8305 |
| Firefox | All modern | RFC 8305 |
| Safari | All modern | RFC 8305 |
| curl | 7.19.0+ | RFC 8305 (--happy-eyeballs-timeout-ms) |
| Python | 3.12+ | asyncio Happy Eyeballs |
| Go | 1.12+ | net.Dialer |
Monitoring Happy Eyeballs
You can observe Happy Eyeballs behavior with curl:
# See which protocol won the race
curl -v --happy-eyeballs-timeout-ms 300 https://example.com 2>&1 | grep "Connected to"
# Force IPv6 only (disable Happy Eyeballs)
curl -6 https://example.com
# Force IPv4 only
curl -4 https://example.com
Impact on IPv6 Adoption
Happy Eyeballs has been crucial for IPv6 deployment. It gives network operators confidence to enable IPv6 -- if something goes wrong, clients automatically and quickly fall back to IPv4. Users never notice the transition.