The single most effective change you can make to improve proxy performance is not buying a faster proxy; it is reusing the existing connection. A client that opens a new connection for every request pays the connection setup cost over and over, and that cost compounds when it goes through a proxy.
The Real Cost of Establishing a Connection
These 200 ms are paid again on every new connection. If you send 1,000 requests and open a new connection each time, you spend 200 seconds on setup alone.
How Does Keep-Alive Work?
In HTTP/1.1 connections are persistent by default: the connection is not closed once the response arrives, and the next request is sent over the same socket. Three things break this behaviour:
- The server sends
Connection: closeback — the connection is closed. - The client creates a new session object for every request — the pool never works.
- The idle timeout is exceeded — the proxy or the server drops the connection.
Creating a new Session, Client or Agent object for every request in the code. This completely disables connection reuse, whatever your pool configuration may be.
The Correct Configuration
Keep the pool size just below your provider's concurrency limit. If you exceed it, extra connections are opened and immediately closed.
How Much Do You Gain?
In the example measurement, using a pool cuts the total time to roughly one third. The gain grows as the latency to the proxy increases.
TLS Session Reuse
Alongside the connection pool there is a second source of gains: the TLS session ticket. When reconnecting to the same target, an abbreviated handshake can be performed instead of a full one. Most modern clients do this automatically; what matters is reusing the client object.
If you recreate the client object on every request, the session ticket is lost and a full handshake is performed every time.
Balancing the Idle Timeout
Keeping a connection open for too long can cause problems too: the proxy or the target server may silently drop the connection and your client only notices this on the next request. This leads to the "first request fails, second one succeeds" pattern.
| Setting | Recommended | Why |
|---|---|---|
| keepalive_expiry | 30–60 s | Must be shorter than the server timeout |
| Pool size | Below the concurrency limit | Anything more is a wasted handshake |
| Retry | Once | Compensates for a dropped connection |
| Connection lifetime limit | 5–10 min | Long-lived connections go stale |
Keep the idle timeout shorter than the server's timeout. That way you are the one closing the connection and the "the server closed it but I do not know" situation never arises.
The Conflict with Rotation
Connection reuse and IP rotation naturally conflict: using the same connection means staying on the same exit IP. This is not a problem but a matter of preference:
In most scenarios the second option is the right one: reuse the connection for a while (for example 30 requests or 5 minutes), then refresh it.
For rotation strategies, see our article on rotation settings .
Summary
Keep-alive and connection pooling are the single biggest lever in proxy performance. Create the client object once and reuse it, keep the pool size below your provider's limit, set the idle timeout shorter than the server's timeout and add a single retry. If you need rotation, prefer periodic refreshing over switching the pool off. For measurement, ping test and proxy checker tools.