# Keep-Alive (Persistent Connections)

> Keep-alive reuses one TCP connection for many HTTP requests. Learn the HTTP/1.1 default, idle timeout defaults in nginx and Node, and why mismatches cause 502s.

Source: https://howhttpworks.com/glossary/keep-alive
Last reviewed: 2026-10-04

> **TL;DR:** Keep-alive means reusing one TCP connection for multiple HTTP requests. It has been the HTTP/1.1 default since the start; the risk now is a timeout mismatch between two hops, which shows up as random 502s.

Keep-alive, formally a persistent connection, is HTTP/1.1 behavior in which the connection stays open after a response so further requests can reuse it instead of paying for a new TCP and TLS handshake. In HTTP/1.0 you had to opt in with `Connection: keep-alive`; in HTTP/1.1 you opt out with `Connection: close`.

## On the wire

```http
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 27
Connection: keep-alive
Keep-Alive: timeout=5
```

In HTTP/1.1 the `Connection` header here is redundant. The `Keep-Alive` header is an advisory hint that RFC 9110 and 9112 do not define; support is inconsistent. Persistence also requires the message length to be known, through `Content-Length` or chunked encoding, so the client knows where one response ends.

## Defaults worth knowing

- **nginx:** `keepalive_timeout 75s` for clients. Connections to upstreams are not kept alive unless you configure `proxy_http_version 1.1`, an empty `Connection` header and an `upstream` `keepalive` pool.
- **Apache:** `KeepAliveTimeout 5` seconds.
- **Node.js:** `server.keepAliveTimeout` defaults to 5000 ms in current releases (still true in Node 26.10). A change merged upstream raises the default to 65000 ms in a future release, so set it explicitly rather than relying on your version's default.

## Non-obvious facts

- **The 502 race.** If a load balancer's idle timeout (60 seconds by default on an AWS ALB) is longer than the backend's, the backend can close a connection at the same moment the balancer reuses it. The balancer sees a reset and returns 502. Set the backend's keep-alive timeout above the balancer's idle timeout; in Node, raise `keepAliveTimeout` (and keep `headersTimeout` above it).
- **Reuse saves round trips.** A new HTTPS connection costs a TCP handshake plus a [TLS handshake](https://howhttpworks.com/glossary/tls-handshake) before the first byte of the request.
- **Retries on a dead connection are only safe for idempotent requests.** If the connection was closed, a client may resend a `GET` automatically, but a `POST` is not safely repeatable; see [idempotent](https://howhttpworks.com/glossary/idempotent).
- **HTTP/1.1 reuse is serial.** Each connection handles one request at a time, which is why browsers open several per host. HTTP/2 removes that limit.
- **Idle connections cost memory.** Long timeouts on a busy server pin file descriptors, so the default is a trade-off, not a free win.

## Go deeper

- [Keep-Alive header](https://howhttpworks.com/headers/keep-alive)
- [Connection header](https://howhttpworks.com/headers/connection)
- [Request and response lifecycle](https://howhttpworks.com/guides/request-lifecycle)
- [nginx 502 Bad Gateway](https://howhttpworks.com/debug/nginx-502-bad-gateway)
