On this page
TCP keepalive
A mechanism at the transport layer that periodically sends empty probe packets across an idle connection to ensure the peer is still reachable and to prevent firewalls from dropping the connection.
Reference Card
- Origin/Prior Art: Original TCP specifications (RFC 1122, updated by RFC 9293).
- Related Practices: Connection pooling, Load balancer timeouts.
- Key Concepts: Idle timeout, Stateful firewalls, Half-open connections.
- Primary Failure Modes: Silent connection drops leading to application deadlocks, Wasting resources by keeping connections alive unnecessarily.
Introduction
Establishing a TCP connection requires a three-way handshake, which is slow and computationally expensive, especially when encrypted with TLS. To maximize performance, modern applications use connection pools - keeping established connections open indefinitely and reusing them for multiple HTTP requests or database queries.
However, if an application leaves a connection idle for two hours, how does it know the server at the other end hasn’t crashed in the meantime? Furthermore, modern networks are heavily guarded by stateful firewalls and NAT (Network Address Translation) routers. If a firewall sees a connection sitting completely idle for 10 minutes, it assumes the connection is dead and silently purges it from its routing table to save memory.
TCP Keepalive solves this by having the operating system automatically transmit invisible “heartbeat” packets over idle connections.
Mental Model
Think of holding a phone to your ear while the person on the other end reads a very long document. If they don’t speak for five minutes, you might assume the call dropped and hang up. TCP Keepalive is the equivalent of them periodically saying, “Still here,” even when they have no actual data to transmit. It guarantees to both you (the client) and the phone company (the firewall) that the line is still actively in use.
Operational Pattern
TCP Keepalive is a feature of the operating system’s network stack, not the application layer (like an HTTP ping or a Database SELECT 1).
It is controlled by three primary kernel parameters (using Linux as the standard):
tcp_keepalive_time: How long the connection must be completely idle before the OS sends the first keepalive probe (default is often 7200 seconds / 2 hours).tcp_keepalive_intvl: If the probe is not acknowledged, how long to wait before sending the next probe (default is often 75 seconds).tcp_keepalive_probes: How many consecutive probes must fail before the OS declares the connection dead and forcibly closes it (default is often 9).
When a developer enables keepalives on a socket (e.g., via setsockopt(SO_KEEPALIVE) in C or socket.setKeepAlive(true) in Node.js), the kernel handles the heartbeat entirely in the background. The application code remains completely unaware until the kernel explicitly throws a connection error.
Failure Modes
The Silent Drop (Half-Open Connections)
The most common TCP failure mode in cloud environments occurs when the default tcp_keepalive_time (2 hours) is longer than the cloud provider’s firewall idle timeout (e.g., AWS NAT Gateways aggressively drop idle connections after 5 minutes).
If your application opens a connection to a database and goes idle, the AWS firewall drops the connection at minute 5. Neither the application nor the database is notified (a “silent drop”). When the application tries to send a query at minute 10, it writes to a socket that it believes is open, but the firewall drops the packet into a black hole. The application will hang indefinitely, waiting for an acknowledgment that will never arrive. The fix is to aggressively tune tcp_keepalive_time down to 60 seconds.
The Battery Drain
On mobile devices (iOS/Android), waking up the cellular radio to transmit a TCP Keepalive packet every 60 seconds will catastrophically drain the user’s battery. Mobile applications should generally avoid long-lived idle TCP connections, relying instead on push notification architectures or aggressively shutting down connections and accepting the latency penalty of reconnecting.
Security
TCP Keepalives consume minimal bandwidth, but they do consume resources. Malicious actors can open thousands of connections to a server and deliberately ignore keepalive probes to exhaust the server’s socket limits (a variant of a Slowloris attack). Web servers and load balancers must be configured with hard timeouts at the application layer to forcefully terminate connections that have not transmitted valid HTTP data within a reasonable timeframe, regardless of TCP Keepalive status.
Operational Guidance
In a microservices architecture, you should almost always override the OS default keepalive settings. A 2-hour idle timeout is a relic of the 1990s internet.
When configuring connection pools in your application (e.g., HikariCP for Java, or the standard database/sql package in Go), explicitly enable keepalives and set the idle threshold to 1 or 2 minutes. This ensures dead connections are aggressively purged from the pool before the application attempts to use them for live customer traffic.