TL;DR: The side that closes the connection first holds TIME_WAIT for twice the maximum segment lifetime, typically 60 seconds on Linux. A proxy making many short-lived outbound connections exhausts its roughly 28,000 default ephemeral ports per destination tuple. The real fix is connection reuse, not kernel tuning, and
tcp_tw_recycleis not an option because it was removed for breaking NAT.
How to approach it
Establish who accumulates TIME_WAIT and why it exists before offering fixes, because the reason it exists is what rules out the popular fixes.
A strong answer
TIME_WAIT belongs to whichever peer initiated the close. It lasts 2×MSL, 60 seconds on Linux, and it serves two purposes: absorbing delayed duplicate segments from the closed connection so they cannot be delivered to a new connection reusing the same four-tuple, and ensuring the final ACK can be retransmitted if lost. It is correctness machinery, not waste.
The exhaustion is arithmetic. A connection is identified by source IP, source port, destination IP and destination port. For a proxy talking to one backend IP and port, only the source port varies, and net.ipv4.ip_local_port_range defaults to roughly 32768 to 60999, about 28,000 ports. At 60 seconds of TIME_WAIT, under a one-source-IP, no-TIME_WAIT-reuse assumption, roughly 460 closes per second to a single destination can occupy the range and new connects fail with EADDRNOTAVAIL.
The fixes, in order of how much I would recommend them.
Connection reuse is the real answer. Keep-alive on the upstream side, a connection pool sized to your concurrency, HTTP/2 multiplexing. A proxy that reuses connections does not accumulate TIME_WAIT because it is not closing them. This removes the problem rather than raising the ceiling, and every other option is a workaround.
Widen the tuple. More backend IPs, or more source IPs on the proxy, multiply the available combinations directly. Talking to a load balancer with several addresses rather than one is often the easiest structural change available.
Widen the port range. ip_local_port_range to 1024–65535 buys you roughly double. Reserve listening-service ports with ip_local_reserved_ports, verify runtime policy and test the change; it adds headroom without fixing churn.
tcp_tw_reuse allows reusing a TIME_WAIT socket for a new outbound connection when timestamps show it is safe. Reasonable for outbound-heavy hosts and it only affects the connecting side.
What you must not reach for is tcp_tw_recycle. It broke connections from clients behind NAT, because it made assumptions about timestamp monotonicity per source IP that multiple hosts behind one address violate. It was removed from the kernel in 4.12, and proposing it signals that your knowledge came from a blog post older than the fix.
What interviewers probe next
"Is TIME_WAIT on the server side a problem?" Usually not. The server accepts on one port, so it is not consuming ephemeral ports, and the memory per socket is small. It is the client or proxy side that hurts.
"How would you confirm the diagnosis?" ss -s for the state summary, and a destination-filtered ss -tan state time-wait count, correlated with EADDRNOTAVAIL and the source port range to see whether it is concentrated on one backend.
"What is CLOSE_WAIT and why is it worse?" CLOSE_WAIT means the peer closed and your application has not called close. It never times out on its own, so persistent unexplained growth can indicate leaked descriptors. A deliberate half-close can be valid while the local side finishes sending.
Common mistakes
Recommending tcp_tw_recycle, which is the fastest way to fail this question.
Tuning the kernel first. Connection reuse fixes the cause and tuning raises a ceiling you will hit again.
Confusing TIME_WAIT with CLOSE_WAIT. Both are protocol states; unexplained growing CLOSE_WAIT usually requires application lifecycle investigation.
References