---
title: "Latency Incident Report: Socket Bind Before Connect"
description: "An August 11, 2016 incident caused increased routing latency in Heroku’s EU Common Runtime, even though CPU, packet, memory, request, and socket metrics remained normal. The routing layer received EADDRINUSE while connecting to dynos, leading engineers to investigate Linux TCP port allocation, TIME_WAIT, and the Erlang VM’s system calls with strace. They found that the VM called bind() with 0.0.0.0:0 before connect(), forcing Linux to allocate an ephemeral source port without knowing the destination; this made the ephemeral port range an effective per-instance traffic limit and could fail before 65,536 connections. Testing reproduced the failures and showed that setting SO_REUSEADDR before bind(), exposed in Erlang as {reuseaddr, true}, removed the bind errors; the corresponding Vegur patch was deployed a few days later."
---

# Latency Incident Report: Socket Bind Before Connect

[Heroku](https://yomu.fyi/company/heroku) · Lex Neva · Mar 30, 2017

**Type:** Incident / postmortem

## Summary

An August 11, 2016 incident caused increased routing latency in Heroku’s EU Common Runtime, even though CPU, packet, memory, request, and socket metrics remained normal. The routing layer received EADDRINUSE while connecting to dynos, leading engineers to investigate Linux TCP port allocation, TIME\_WAIT, and the Erlang VM’s system calls with strace. They found that the VM called bind() with 0.0.0.0:0 before connect(), forcing Linux to allocate an ephemeral source port without knowing the destination; this made the ephemeral port range an effective per-instance traffic limit and could fail before 65,536 connections. Testing reproduced the failures and showed that setting SO\_REUSEADDR before bind(), exposed in Erlang as {reuseaddr, true}, removed the bind errors; the corresponding Vegur patch was deployed a few days later.

## Context

On August 11, 2016, Heroku saw increased routing latency in the EU region of the Common Runtime. Standard indicators, including CPU, packet rates, memory, request rates, and socket usage, were normal or better than in the US. The routing layer was also receiving the unexpected EADDRINUSE error while connecting to dynos, prompting an investigation into Linux networking and the Erlang VM.

## Approach / What changed

Engineers traced the Erlang VM’s socket calls with strace and found that it called bind() with 0.0.0.0:0 before connect(). They reproduced the resulting port-allocation failures with a C program, then added SO\_REUSEADDR before bind() and confirmed the behavior. The Erlang fix used {reuseaddr, true}, and the change was applied to the Vegur HTTP proxy library.

## Takeaways

- Calling bind() before connect() makes Linux choose an ephemeral source port without destination information, imposing a much tighter effective limit than the TCP 4-tuple model suggests.
- Linux can return EADDRINUSE during ephemeral-port allocation before 65,536 connections because it randomly probes a limited sequence of candidate ports rather than scanning every port.
- Setting SO\_REUSEADDR before bind() resolved the reproduced failures, and the Erlang equivalent is the {reuseaddr, true} socket option.

**Tags:** [Debugging](https://yomu.fyi/topic/debugging), [Erlang](https://yomu.fyi/topic/erlang), [Linux](https://yomu.fyi/topic/linux)

- Source: [Heroku](https://www.heroku.com/blog/sockets-in-a-bind)
- Source URL: https://www.heroku.com/blog/sockets-in-a-bind
- Ingested by Yomu: 2026-09-09T14:25:12.343Z

[Read original post](https://www.heroku.com/blog/sockets-in-a-bind)
