How to reduce TCP sockets in TIME_WAIT

Diagnose connection churn and port pressure before tuning TIME_WAIT. Start with connection reuse and distinguish socket state from conntrack usage.

Best practices
Illustration of application infrastructure and operations

TIME_WAIT is a normal TCP state, generally entered by the endpoint that actively closes a connection. Its waiting period protects subsequent connections from delayed packets and supports reliable connection termination. A high count alone does not establish a fault.

If connection churn is causing a real problem, start with HTTP connection reuse and database pools. Consider port ranges, egress addresses, or load distribution only after identifying the bottleneck. Kernel settings are not a universal shortcut.

Establish whether there is a problem

On Linux, inspect the current socket counts:

ss -s
ss -ant | grep TIME_WAIT | wc -l

Compare these counts with new-connection failures, ephemeral port configuration, source addresses, and connection tuples. There is no universal threshold below which a host is “safe.” Cannot assign requested address can indicate port pressure, but it can also mean an application tried to bind an unavailable address.

Socket state and firewall connection tracking are separate measurements. A TIME_WAIT count is not a conntrack utilization count.

Reduce unnecessary connection creation

A service that opens and closes a TCP connection for every request creates more closing-state churn than one that reuses connections.

  • HTTP clients: check the library and version's connection-reuse behavior. Reuse an appropriate client/pool instead of creating a new client per request.
  • Databases: use a suitable pool, such as HikariCP or PgBouncer, instead of connecting for each query.
  • Service calls: HTTP/2 and gRPC can multiplex requests over connections; actual connection counts still depend on client configuration and workload.
  • Nginx upstreams: configure an upstream keepalive cache and appropriate HTTP/1.1 proxy settings, including proxy_http_version 1.1 and an empty Connection header. Changing headers alone does not establish an upstream pool.

Compare connection creation, TIME_WAIT, and error rates under equivalent request loads. The improvement depends on the previous behavior; it cannot be predicted as a fixed multiplier.

Guance's NetStat integration records tcp_time_wait. Use addr_ports or ports_match when you need port-specific collection, and compare the trend with actual connection failures.

Inspect Linux settings before considering changes

Start with read-only inspection:

sysctl net.ipv4.tcp_tw_reuse
sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.ip_local_reserved_ports

Current upstream Linux documentation defines tcp_tw_reuse values as disabled (0), globally enabled (1), and enabled for loopback only (2), with a documented default of 2. Check your kernel and distribution: this is not a promise about every installed system. The kernel documentation advises against changing it without expert guidance. Do not treat tcp_tw_reuse=1 as an automatically safe client-side fix.

Before expanding ephemeral ports, check reserved ports, local listeners, outbound NAT, and network namespaces. Record the existing values and a rollback plan.

Two frequently repeated suggestions are misleading:

  • tcp_tw_recycle was removed in Linux 4.12; older implementations could break connections involving NAT. Do not try to restore this obsolete setting.
  • tcp_fin_timeout concerns orphaned FIN_WAIT2 connections, not the TIME_WAIT duration.

Distribute traffic only when the bottleneck warrants it

If measurements establish an ephemeral-port or egress-NAT limit, possible approaches include additional egress addresses, distribution across backend destinations, or a connection-aggregation layer. Capacity depends on source addresses, available ports, destinations, and NAT behavior; it is not a fixed connection count per machine.

Adding a NIC or address does not automatically distribute outbound connections. Routing, source selection, or NAT rules must actually use the additional addresses. More backend nodes help only when traffic distribution changes the constrained resource.

Frequently asked questions

Is CLOSE_WAIT worse than TIME_WAIT?

Neither state alone determines severity. Brief CLOSE_WAIT is normal. Persistent growth calls for checking whether the application closes sockets after receiving the peer's FIN, whether threads are blocked, and whether descriptors are exhausted. TIME_WAIT is part of normal connection shutdown.

Is TIME_WAIT behind a load balancer normal?

It can be. With a new backend connection for every request, the endpoint that actively closes normally accumulates TIME_WAIT; that may be the load balancer or backend. Connection reuse can reduce churn, but measure the effect and check which side closes first.

Can TIME_WAIT affect performance?

Heavy connection churn can increase memory, port, and NAT/conntrack pressure. Check those resources separately and correlate with errors. A socket count is useful evidence, not a diagnosis on its own.

References

Related reading

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting