- Home
- HTTP Headers
- Keep-Alive Header
Header
Keep-Alive Header
Learn how the Keep-Alive header controls HTTP connection persistence and reuse. Reduce latency and improve performance by avoiding repeated TCP handshakes.
What is Keep-Alive?
TL;DR: Provides parameters for persistent connections like timeout and max requests. Helps optimize connection reuse for better performance.
The Keep-Alive header allows the client and server to negotiate parameters for persistent connections. It enables multiple HTTP requests and responses to be sent over a single TCP connection, reducing latency and improving performance.
While HTTP/1.1 uses persistent connections by default, the Keep-Alive header provides fine-grained control over connection behavior, such as timeout and maximum requests.
How Keep-Alive Works
Client requests persistent connection:
GET /api/users HTTP/1.1
Host: api.example.com
Connection: keep-alive
Keep-Alive: timeout=5, max=100
```text
**Server acknowledges:**
```http
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=100
Content-Type: application/json
{"users": [...]}
Syntax
Keep-Alive: timeout=<seconds>
Keep-Alive: max=<requests>
Keep-Alive: timeout=<seconds>, max=<requests>
```text
### Parameters
- **timeout** - Time in seconds the connection should remain open when idle
- **max** - Maximum number of requests that can be sent on this connection before closing
## Common Examples
### Basic Keep-Alive
```http
Connection: keep-alive
Keep-Alive: timeout=5
Keeps connection open for 5 seconds of idle time.
With Maximum Requests
Connection: keep-alive
Keep-Alive: timeout=10, max=1000
```text
Keeps connection open for 10 seconds, allows up to 1000 requests.
### Long-Lived Connection
```http
Connection: keep-alive
Keep-Alive: timeout=120, max=5000
Suitable for applications with frequent requests.
Real-World Scenarios
API Gateway Configuration
# Client to API Gateway
GET /api/products HTTP/1.1
Host: gateway.example.com
Connection: keep-alive
Keep-Alive: timeout=60, max=1000
# Gateway to Client
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=60, max=1000
Content-Type: application/json
```text
### High-Traffic Web Server
```http
# Server response
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: timeout=15, max=500
Content-Type: text/html
Balances connection reuse with resource management.
Microservices Communication
GET /internal/user-service/profile HTTP/1.1
Host: internal.services
Connection: keep-alive
Keep-Alive: timeout=30, max=2000
```text
Internal services benefit from long-lived connections.
## HTTP/1.0 vs HTTP/1.1
### HTTP/1.0 (Explicit Keep-Alive)
```http
# Client must explicitly request
GET / HTTP/1.0
Connection: keep-alive
Keep-Alive: timeout=5, max=100
# Server must explicitly agree
HTTP/1.0 200 OK
Connection: keep-alive
Keep-Alive: timeout=5, max=100
HTTP/1.1 (Default Persistent)
# Persistent by default, no header needed
GET / HTTP/1.1
Host: example.com
# Server can override
HTTP/1.1 200 OK
Keep-Alive: timeout=5, max=100
```text
## Closing Connections
### Client Closes Connection
```http
GET /api/logout HTTP/1.1
Host: api.example.com
Connection: close
Explicitly closes after response.
Server Signals Last Response
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
{"message": "Goodbye"}
```javascript
Server indicates connection will close after this response.
## Server Configuration Examples
### Node.js (Express)
```javascript
const express = require('express')
const app = express()
// Configure keep-alive settings
const server = app.listen(3000, () => {
server.keepAliveTimeout = 65000 // 65 seconds
server.headersTimeout = 66000 // Slightly higher than keep-alive
})
// Set keep-alive header in responses
app.use((req, res, next) => {
res.set('Keep-Alive', 'timeout=65, max=1000')
next()
})
app.get('/api/data', (req, res) => {
res.json({ data: 'example' })
})
Nginx
http {
keepalive_timeout 65; # 65 seconds timeout
keepalive_requests 1000; # Max 1000 requests per connection
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # Enable keep-alive to backend
}
}
}
```text
### Apache
```apache
# Enable keep-alive
KeepAlive On
# Maximum requests per connection
MaxKeepAliveRequests 100
# Timeout in seconds
KeepAliveTimeout 5
Client Implementation
JavaScript (Fetch API)
// Fetch API uses keep-alive by default
fetch('https://api.example.com/data', {
headers: {
Connection: 'keep-alive'
}
})
.then((response) => response.json())
.then((data) => console.log(data))
```javascript
### Node.js HTTP Agent
```javascript
const http = require('http')
// Create agent with keep-alive enabled
const agent = new http.Agent({
keepAlive: true,
keepAliveMsecs: 30000, // 30 seconds
maxSockets: 50,
maxFreeSockets: 10
})
// Use agent for requests
http.get(
{
hostname: 'api.example.com',
path: '/data',
agent: agent
},
(res) => {
res.on('data', (chunk) => console.log(chunk.toString()))
}
)
Python (requests)
import requests
from requests.adapters import HTTPAdapter
# Create session with connection pooling (keep-alive)
session = requests.Session()
adapter = HTTPAdapter(pool_connections=10, pool_maxsize=100)
session.mount('https://', adapter)
# Reuses connections automatically
response1 = session.get('https://api.example.com/users')
response2 = session.get('https://api.example.com/posts')
response3 = session.get('https://api.example.com/comments')
```text
### cURL
```bash
# cURL uses keep-alive by default in HTTP/1.1
curl https://api.example.com/data
# Explicitly disable keep-alive
curl -H "Connection: close" https://api.example.com/data
# View connection details
curl -v https://api.example.com/data
Performance Benefits
Without Keep-Alive
Request 1: TCP handshake → HTTP request → Response → Close
Request 2: TCP handshake → HTTP request → Response → Close
Request 3: TCP handshake → HTTP request → Response → Close
Total: 3 TCP handshakes (3-way handshake each = 9 round trips)
With Keep-Alive
Connection: TCP handshake →
Request 1 → Response →
Request 2 → Response →
Request 3 → Response →
Close
Total: 1 TCP handshake (3 round trips)
Saves significant latency, especially with TLS (which adds more handshake overhead).
Best Practices
For Servers
1. Set reasonable timeouts
# ✅ Balanced timeout
Keep-Alive: timeout=30, max=1000
# ❌ Too short (defeats purpose)
Keep-Alive: timeout=1, max=10
# ❌ Too long (wastes resources)
Keep-Alive: timeout=300, max=10000
```javascript
**2. Consider server load**
```javascript
// Adjust based on traffic
const keepAliveTimeout = highTraffic ? 15000 : 60000
server.keepAliveTimeout = keepAliveTimeout
3. Monitor connection limits
const server = app.listen(3000)
// Prevent resource exhaustion
server.maxConnections = 1000
setInterval(() => {
console.log('Active connections:', server.connections)
}, 5000)
```javascript
### For Clients
**1. Reuse connections with connection pooling**
```javascript
// ✅ Use connection pooling
const agent = new http.Agent({ keepAlive: true })
// ❌ Create new connection each time
const agent = new http.Agent({ keepAlive: false })
2. Close connections when done
// Graceful shutdown
process.on('SIGTERM', () => {
server.close(() => {
console.log('Server closed')
process.exit(0)
})
})
```text
**3. Handle connection errors**
```javascript
agent.on('error', (err) => {
console.error('Agent error:', err)
})
Common Issues
Proxy Complications
# Client → Proxy
Connection: keep-alive
Keep-Alive: timeout=60
# Proxy might not forward Keep-Alive to origin
# Or might use different settings
```text
Some proxies strip or modify Keep-Alive headers.
### Load Balancer Timeouts
```nginx
# Load balancer timeout must be > backend timeout
proxy_connect_timeout 70s;
proxy_send_timeout 70s;
proxy_read_timeout 70s;
# Backend keep-alive timeout
keepalive_timeout 65s;
Connection Pool Exhaustion
// ✅ Limit pool size
const agent = new http.Agent({
keepAlive: true,
maxSockets: 50, // Limit concurrent connections
maxFreeSockets: 10 // Limit idle connections
})
```text
## HTTP/2 and HTTP/3
Keep-Alive is not used in HTTP/2 and HTTP/3:
- **HTTP/2** uses multiplexing over a single connection
- **HTTP/3** uses QUIC protocol with built-in connection management
```http
# HTTP/2 - No Keep-Alive header needed
:method: GET
:path: /api/data
:scheme: https
:authority: example.com
Security Considerations
Connection Timeout Attacks
// Prevent slowloris attacks
server.keepAliveTimeout = 65000
server.headersTimeout = 66000 // Must be > keepAliveTimeout
server.requestTimeout = 300000 // Maximum request time
```text
### Resource Limits
```nginx
# Limit connections per IP
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 10;
# Prevent too many idle connections
keepalive_timeout 30;
keepalive_requests 100;
Related Headers
- Connection - Control connection options
- Upgrade - Protocol upgrade mechanism
- Content-Length - Required for keep-alive in HTTP/1.0
Frequently Asked Questions
What is the Keep-Alive header?
Keep-Alive provides parameters for persistent connections: timeout (seconds to keep open) and max (maximum requests). Used with Connection: keep-alive.
Is Keep-Alive still relevant?
Less so in HTTP/2 and HTTP/3 which manage connections differently. In HTTP/1.1, it helps clients understand connection limits.
What does timeout parameter mean?
timeout=5 means the server will keep the connection open for 5 seconds of inactivity. After that, it may close the connection.
What does max parameter mean?
max=100 means the connection can be reused for up to 100 requests. After that, a new connection is needed. Helps servers manage resources.