Node.js Axios HTTP Connection Reuse Guide
This article examines how HTTP connection reuse (HTTP Keep-Alive) impacts the performance of the Axios client within Node.js applications. By default, Node.js destroys TCP sockets after each request unless explicitly configured otherwise. Enabling persistent connections dramatically improves application latency, reduces CPU overhead, prevents socket exhaustion under heavy load, and increases overall network throughput.
The Default Connection Behavior in Node.js
When Axios runs in a Node.js environment, it utilizes the native
http and https modules to dispatch network
requests. By default, the global Node.js HTTP/HTTPS agents do not reuse
connections between individual requests; they terminate the underlying
TCP socket once a response finishes.
Each subsequent HTTP request requires a new TCP three-way handshake. For HTTPS traffic, this also requires a full TLS handshake, which involves multiple network round-trips and cryptographic operations before any application data is sent.
Key Impacts of HTTP Connection Reuse
1. Significant Latency Reduction
Reusing existing connections eliminates the round-trip times (RTT) required for TCP and TLS handshakes. For remote APIs or microservices, handshake overhead can easily add 50ms to 200ms per request. With Keep-Alive enabled, subsequent requests send HTTP payloads immediately over an established socket, cutting overall response times down to the bare network transit and processing time.
2. Lower CPU and Memory Consumption
The TLS handshake is computationally expensive because it involves asymmetric cryptography. When connections are reused across dozens or hundreds of requests, the CPU overhead on both the client application and the target server drops significantly, freeing up server resources for request processing.
3. Prevention of Socket Exhaustion (TIME_WAIT State)
When a client closes a TCP connection, the socket lingers in a
TIME_WAIT state for a defined operating system duration
(typically 60 to 120 seconds) to ensure delayed packets are handled
correctly. Under high request volumes, opening and closing thousands of
connections rapidly depletes the pool of available ephemeral ports,
leading to EADDRNOTAVAIL or ECONNRESET errors.
Connection reuse maintains a steady pool of active sockets, preventing
port starvation.
4. Increased Application Throughput
Because network sockets stay open and ready for immediate I/O, the Node.js event loop spends less time managing low-level connection lifecycles. This allows the application to handle a higher volume of concurrent outgoing requests.
How to Configure Connection Reuse in Axios
To enable connection reuse in Axios, you must instantiate custom
http.Agent and https.Agent instances with
keepAlive: true and attach them to an Axios instance.
const axios = require('axios');
const http = require('http');
const https = require('https');
const httpAgent = new http.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 10,
timeout: 60000,
});
const httpsAgent = new https.Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 10,
timeout: 60000,
});
const apiClient = axios.create({
baseURL: 'https://api.example.com',
httpAgent,
httpsAgent,
timeout: 5000,
});
module.exports = apiClient;Agent Configuration Options:
keepAlive: Set totrueto keep sockets open for future requests.maxSockets: Defines the maximum number of concurrent sockets allowed per host.maxFreeSockets: The maximum number of idle sockets left open in the pool.timeout: Sets the socket inactive timeout in milliseconds before destroying an idle connection.
Common Considerations
- Server-Side Keep-Alive Timeouts: Servers often
enforce their own idle socket timeouts (e.g., NGINX defaults to 75
seconds, AWS ALB defaults to 60 seconds). Ensure your client agent's
idle timeout or request retry mechanisms account for server-initiated
socket closures to avoid race conditions and
ECONNRESETerrors. - Load Balancers and DNS: Persistent TCP connections bypass DNS lookups on a per-request basis. If your destination relies on dynamic DNS updates or round-robin DNS for load balancing, long-lived sockets may send all traffic to a single backend instance unless the connection is periodically recycled.