TCP keepalive settings control how long-idle connections are detected and maintained — important for connections through NAT, firewalls, or load balancers that might otherwise silently drop idle connections. This guide covers understanding and tuning these settings.
The Problem TCP Keepalive Solves
A TCP connection can appear "established" indefinitely from an application's perspective, but intermediate network devices (NAT gateways, stateful firewalls, load balancers) often silently drop connection state for idle connections after some timeout — the application doesn't know the connection is actually dead until it tries to use it and fails.
How TCP Keepalive Works
Periodic probe packets sent during idle periods confirm the connection is still genuinely alive — if probes go unanswered after a configured number of retries, the OS considers the connection dead and notifies the application, rather than leaving it in an ambiguous "maybe still alive" state.
Checking Current Keepalive Settings
sysctl net.ipv4.tcp_keepalive_time
sysctl net.ipv4.tcp_keepalive_intvl
sysctl net.ipv4.tcp_keepalive_probes
Understanding the Three Key Parameters
| Parameter | Meaning | Common Default |
|---|---|---|
| tcp_keepalive_time | Idle time before first probe sent | 7200 seconds (2 hours) |
| tcp_keepalive_intvl | Interval between probe retries | 75 seconds |
| tcp_keepalive_probes | Number of failed probes before declaring connection dead | 9 |
Why Default Settings Are Often Too Conservative
The default 2-hour initial idle period is often longer than many NAT/firewall idle timeouts (commonly much shorter) — meaning the connection may already be silently dropped by an intermediate device long before your keepalive would even send its first probe.
Setting More Aggressive Keepalive for Long-Lived Connections
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 4
sudo sysctl -p
A 5-minute initial idle period with more frequent, faster-failing probes detects dead connections much sooner — particularly relevant for database connections, persistent API connections, or any long-lived connection through NAT/firewall infrastructure.
Application-Level Keepalive Configuration
const client = new Client({
keepAlive: true,
keepAliveInitialDelayMillis: 10000,
});
Many database clients and connection libraries support their own application-level keepalive settings, sometimes independent of OS-level TCP settings — check your specific client library's documentation, since both layers can matter.
Keepalive for SSH Connections
ClientAliveInterval 60
ClientAliveCountMax 3
See related SSH configuration for keeping SSH sessions alive through network intermediaries — a common, practical application of this same underlying concept, directly configurable in sshd_config.
Balancing Keepalive Aggressiveness with Overhead
Very aggressive keepalive (frequent probes) adds a small amount of ongoing network overhead — for most use cases this is negligible, but consider the trade-off for genuinely high-connection-count scenarios where the cumulative overhead across many connections could matter.
Common Errors
Long-lived connections still dropping despite keepalive configuration — verify the setting was actually applied (check sysctl values after reboot, since /etc/sysctl.conf changes need to persist correctly), and confirm both ends of the connection have reasonable keepalive settings, not just your server.
Continue Reading
- How to Diagnose and Fix High Network Latency
- How to Set Up a Reverse SSH Tunnel for Remote Access
- How to Diagnose Network Packet Loss on a VPS
Browse more articles in Advanced Networking & VPN.