iServerSupport Talk to an engineer

Too Many TIME_WAIT Connections on Linux: Diagnose the Cause

Learn when Linux TIME_WAIT connections are normal, how to find connection churn or port exhaustion, and which unsafe sysctl tweaks to avoid.

Linux administrator diagnosing a high number of TIME_WAIT TCP connections

Thousands of sockets in TIME_WAIT can look alarming, but the state itself is a normal part of TCP. It prevents delayed packets from an old connection being mistaken for data belonging to a new connection that uses the same address and port combination.

The useful question is not “How do I delete TIME_WAIT sockets?” It is “Which service is opening and closing so many connections, and is that causing a measurable limit?”

This guide shows how to answer that question before applying kernel settings copied from an old tuning checklist.

What TIME_WAIT means

The endpoint that actively closes a TCP connection normally enters TIME_WAIT. On a web stack, that endpoint might be a visitor, a reverse proxy, an application server, a database client or the server itself, depending on how the connection is closed.

A large count may simply reflect healthy traffic. It becomes operationally relevant when it is accompanied by symptoms such as:

  • Outbound connections failing with Cannot assign requested address
  • A proxy or application exhausting its ephemeral source ports
  • Connection tracking approaching its configured limit
  • Latency or errors caused by opening a new connection for every request
  • Unexpected connection churn between two services that should use persistent connections

TIME_WAIT does not consume an application file descriptor because the application has already closed the socket. It still uses kernel state, but the count alone does not prove a memory or performance problem.

Count the sockets and record a baseline

Start with a summary:

ss -s

Count current TIME_WAIT sockets:

ss -tan state time-wait | tail -n +2 | wc -l

Take several samples during normal and peak traffic. A single large number without traffic context can lead to the wrong conclusion.

View a sample of the actual address pairs:

ss -tan state time-wait | head -50

The local and peer columns reveal whether the churn is concentrated on port 80/443, a database port, a local proxy hop or an outbound API destination. Compare this with reverse-proxy, application and database metrics for the same period.

Find which side is creating the churn

TIME_WAIT sockets no longer belong to a live process, so ss -p may not identify the process that created them. Use the address and port pattern to narrow the path, then inspect active connections and service logs.

Common patterns include:

Reverse proxy to application server

If the local server repeatedly connects from ephemeral ports to the same local or private application port, check upstream keepalive and connection-pool settings in NGINX, HAProxy, Apache or the application runtime.

Application to MySQL, Redis or an external API

Repeated short connections usually indicate that connection pooling is disabled, undersized or failing health checks. Fixing the pool generally produces a larger benefit than changing TCP timers.

Remote clients to a web server

High public web traffic naturally produces TIME_WAIT. Check whether the server is actually near a kernel, conntrack or resource limit before tuning it.

Health checks

A load balancer that opens a new TCP connection every second across many backends can create a visible but harmless baseline. Adjust the check method or interval only if the checks create real overhead.

Check for ephemeral port pressure

Show the configured IPv4 ephemeral port range:

sysctl net.ipv4.ip_local_port_range

Port exhaustion normally affects a client or proxy making many outbound connections to the same destination tuple. The practical fix is persistent connections, pooling or distributing traffic across suitable source and destination addresses. Expanding the port range can provide headroom, but it does not correct uncontrolled connection churn.

Also check whether a stateful firewall or conntrack table is the actual limit:

sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max

Those keys exist only when connection tracking is loaded. If usage is close to the maximum, investigate the traffic mix and firewall design before increasing the limit.

Fix the application path first

The most effective changes usually occur above the kernel:

  1. Enable HTTP keepalive between proxies and application servers.
  2. Use a bounded database or API connection pool.
  3. Reuse SMTP, Redis and other upstream connections when the protocol and workload allow it.
  4. Check whether a failing health check repeatedly opens new connections.
  5. Set realistic application idle timeouts so that both ends agree on connection lifetime.
  6. Scale the proxy or client tier if one source IP genuinely needs more concurrent outbound connection capacity.

After each change, compare request rate, errors, latency and TIME_WAIT creation rate. The objective is a stable service, not a particular socket count.

Kernel settings that are often misunderstood

tcp_fin_timeout does not shorten TIME_WAIT

net.ipv4.tcp_fin_timeout controls how long an orphaned connection can remain in FIN_WAIT_2. It is not the TIME_WAIT lifetime. Lowering it does not solve the issue described in this article.

Do not lower tcp_max_tw_buckets to purge sockets

The Linux kernel documentation warns that tcp_max_tw_buckets exists as a denial-of-service protection limit and should not be lowered artificially. Destroying valid TIME_WAIT state early can trade a visible count for connection correctness problems.

Treat tcp_tw_reuse as an expert setting

Current kernels support several net.ipv4.tcp_tw_reuse modes, and defaults vary with kernel version. The kernel documentation explicitly advises against changing it without technical review. It is not a general switch for making busy web servers faster.

Do not use tcp_tw_recycle

Old articles recommend tcp_tw_recycle. It was unsafe for clients behind NAT and was removed from modern Linux kernels. It should not appear in a current server-tuning plan.

The authoritative descriptions are maintained in the Linux kernel IP sysctl documentation.

A practical investigation sequence

  1. Record ss -s, the TIME_WAIT count and the current request rate.
  2. Identify the dominant local and peer port pairs.
  3. Check logs and metrics for the corresponding proxy, application or upstream service.
  4. Look for port-allocation or conntrack errors, not just a high socket count.
  5. Correct pooling, keepalive or health-check behavior.
  6. Load-test or observe a comparable traffic period.
  7. Consider a kernel change only when measurements identify a kernel limit and a rollback is prepared.

If the server is already dropping requests or exhausting ports, server optimization should examine the entire connection path rather than applying an isolated sysctl value. Our related guide on finding the exact cause of cPanel server load uses the same evidence-first approach.

Server optimization service

Need help finding the real performance bottleneck?

We investigate Linux, web server, PHP and database performance before making measured configuration changes.