1. Library
  2. Computer Networks
  3. Tcp and Udp
  4. Tcp

Updated 9 hours ago

You close a TCP connection. You check netstat. The connection is still there, labeled TIME_WAIT. You wait. It's still there. Thousands of them, sometimes—sockets that should be dead, lingering like ghosts in your connection table.

This isn't a bug. TIME_WAIT is TCP refusing to forget. For sixty seconds after you close a connection, TCP remembers it existed—because the network might not have gotten the memo yet.

What TIME_WAIT Actually Is

When a TCP connection closes, the side that initiates termination enters TIME_WAIT after completing the four-way handshake. The socket stays allocated in the kernel's connection table, preventing that exact combination of local address, local port, remote address, and remote port from being reused immediately.

The duration is 2MSL—twice the Maximum Segment Lifetime. MSL is the theoretical maximum time a TCP segment can survive in the network before being discarded, typically 30 seconds. So TIME_WAIT lasts 60 seconds on most systems, though some use 30 or 120.

During TIME_WAIT, the socket consumes almost nothing—no buffers, no application state. It just occupies an entry in the kernel's connection table and blocks reuse of that specific four-tuple.

Why TCP Refuses to Forget

TIME_WAIT exists for two reasons, both about preventing confusion.

The Lost ACK Problem

TCP's connection teardown ends with an ACK. If that final ACK gets lost, the remote side will retransmit its FIN. Without TIME_WAIT, your system would have already destroyed the connection state. It would respond to the retransmitted FIN with RST, leaving the remote side confused about whether the connection actually closed.

By staying in TIME_WAIT, your system can properly acknowledge retransmitted FINs. Both sides agree the connection is dead. No ambiguity.

The Wandering Packet Problem

Packets take strange paths through networks. They get delayed, rerouted, duplicated. A packet from your old connection might still be wandering the Internet when you create a new connection to the same destination using the same port.

If that old packet arrives, it could be accepted as valid data for the new connection. Data corruption. Silent, invisible, catastrophic.

TIME_WAIT prevents this by refusing to reuse that address/port combination until any possible wandering packets have expired. Two MSLs guarantees every packet from the old connection is dead.

When TIME_WAIT Becomes a Problem

TIME_WAIT is normal. Seeing thousands of TIME_WAIT sockets in netstat just means your system has been busy closing connections. That's fine.

It becomes a problem when you run out of ports.

Each TIME_WAIT socket claims one ephemeral port. Most systems offer roughly 28,000 ephemeral ports (typically 32,768 to 60,999). If you create 28,000 connections to the same destination within 60 seconds, you exhaust the port space. New connections fail with "cannot assign requested address."

This hits:

  • HTTP clients hammering a single API endpoint
  • Load balancers forwarding high traffic volumes
  • Proxy servers
  • Applications with broken connection pooling

The critical detail: TIME_WAIT only blocks reuse of the exact four-tuple. Connections to different destinations don't conflict. A client talking to hundreds of different servers rarely exhausts ports. A client making thousands of requests per second to one server can.

Managing TIME_WAIT

tcp_tw_reuse (Linux)

The net.ipv4.tcp_tw_reuse kernel parameter allows reusing TIME_WAIT sockets for new outbound connections when TCP timestamps prove the new connection is genuinely new. This is safe—timestamps prevent old packets from being accepted—and effectively eliminates port exhaustion for clients.

SO_REUSEADDR

This socket option lets servers bind to a port that has TIME_WAIT sockets from a previous instance. Useful for restarting servers without waiting 60 seconds. It doesn't help with outbound port exhaustion.

Connection Pooling

The real solution is usually architectural: stop creating and destroying connections. HTTP keep-alive, HTTP/2 multiplexing, database connection pools—all avoid TIME_WAIT by reusing connections instead of closing them.

One persistent connection beats a thousand short-lived ones.

When to Worry

TIME_WAIT sockets existing: normal.

TIME_WAIT sockets preventing new connections: problem.

For servers accepting inbound connections, TIME_WAIT almost never matters. Clients use different source ports, so there's no conflict. The server's listening port never enters TIME_WAIT.

For clients or proxies making rapid outbound connections to the same destination, TIME_WAIT can exhaust ports. Enable tcp_tw_reuse, implement connection pooling, or both.

The sockets lingering in your netstat output aren't ghosts haunting your system. They're TCP being careful—remembering connections just long enough to make sure the network has truly moved on.

Frequently Asked Questions About TIME_WAIT

Was this page helpful?

😔
🤨
😃