How to fix Error: TLS handshake timeout (connection timeout during TLS negotiation) in Node.js

Node.jsINTERMEDIATEHIGHUpdated Dec 9, 2025ยท 240 views

A TLS handshake timeout occurs when the client and server fail to complete the SSL/TLS negotiation within the timeout period (default 120 seconds). This typically indicates network delays, server resource constraints, or infrastructure issues.

Quick fix

Fixes Error: TLS handshake timeout (connection timeout during TLS negotiation)

# Test basic TCP connection (ignore SSL errors for now)
curl -v https://your-server.com

# Or use nc/telnet to test the port
nc -zv your-server.com 443
  1. Verify the server is responding to connections
  2. Check server CPU and memory usage
  3. Increase the handshake timeout
  4. Check network connectivity and firewall rules
node.js โ€” error
# Test basic TCP connection (ignore SSL errors for now)
curl -v https://your-server.com
# Or use nc/telnet to test the port
nc -zv your-server.com 443
Error: TLS handshake timeout (connection timeout during TLS negotiation)

What this error means

A TLS (Transport Layer Security) handshake timeout happens when the SSL/TLS connection negotiation between client and server doesn't complete within the configured timeout window. During the handshake phase, the client and server exchange cryptographic information, verify certificates, and negotiate encryption parameters. If this exchange takes longer than the timeout period, the connection is terminated with this error. The default handshake timeout in Node.js is 120 seconds (120,000 milliseconds). This error typically indicates the server is slow to respond, the network has significant latency, or intermediate infrastructure (firewalls, load balancers, proxies) is interfering with the connection.

Typical symptoms

  • HTTPS requests fail with timeout errors instead of connecting
  • Some clients can connect but others consistently timeout
  • Timeout only occurs during initial connection, not after established
  • Increasing timeout threshold temporarily fixes the issue
  • Problem occurs intermittently or increases during high server load
  • Connections work locally but timeout over the internet or through proxies

Common causes

  1. Server is overloaded or under-resourced (CPU, memory), causing slow handshake processing
  2. Network latency between client and server is too high for the default timeout
  3. Firewall, proxy, or load balancer is intercepting or delaying the TLS handshake
  4. Server is performing heavy cryptographic operations without enough resources
  5. TLS version or cipher suite negotiation is causing extended handshake time
  6. Client and server have incompatible TLS configurations or certificate issues

How to fix "Error: TLS handshake timeout (connection timeout during TLS negotiation)"

1Verify the server is responding to connections

First, confirm the server is actually listening and responding. Use curl or telnet to test basic connectivity:

bash
# Test basic TCP connection (ignore SSL errors for now)
curl -v https://your-server.com

# Or use nc/telnet to test the port
nc -zv your-server.com 443

If the server isn't responding at all, restart the Node.js application and check server logs for startup errors.

2Check server CPU and memory usage

A common cause is the server being resource-constrained during the handshake. Monitor server metrics:

bash
# On Linux
top
ps aux | grep node

# On macOS
activity monitor

# Check available memory
free -h  # Linux
vm_stat  # macOS

If CPU is maxed out or memory is low, the handshake processing is delayed. Scale up resources or optimize your application code.

3Increase the handshake timeout

If your server legitimately needs more time (e.g., complex certificate chains or slow networks), increase the handshake timeout in your Node.js TLS configuration:

javascript
const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('server.key'),
  cert: fs.readFileSync('server.cert'),
  handshakeTimeout: 30000  // 30 seconds instead of default 120s
};

const server = https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('OK');
});

server.listen(443);

For client connections making outbound HTTPS requests:

javascript
const https = require('https');

const agent = new https.Agent({
  handshakeTimeout: 30000  // Increase timeout for outbound connections
});

const options = {
  hostname: 'api.example.com',
  port: 443,
  path: '/endpoint',
  method: 'GET',
  agent: agent
};

const req = https.request(options, (res) => {
  console.log('statusCode:', res.statusCode);
});

req.on('error', (error) => {
  console.error('Request failed:', error.message);
});
4Check network connectivity and firewall rules

Verify the network path between client and server isn't introducing excessive delays:

bash
# Test latency to the server
ping your-server.com
mtr your-server.com  # Shows hop-by-hop latency

# Check for packet loss
ping -c 100 your-server.com  # Look for packet loss percentage

Review firewall rules, load balancer configuration, and proxy settings:
- Ensure the firewall isn't rate-limiting or blocking SSL connections
- Check if a load balancer is configured with incompatible TLS settings
- Verify any reverse proxies (nginx, HAProxy) have appropriate timeouts
- Disable any SSL inspection or MITM proxies that might be interfering

5Optimize TLS configuration on the server

Ensure your TLS configuration is efficient:

javascript
const https = require('https');
const fs = require('fs');

const options = {
  key: fs.readFileSync('server.key'),
  cert: fs.readFileSync('server.cert'),

  // Modern, performant cipher suites
  ciphers: 'ECDHE+AESGCM:ECDHE+AES256',

  // Preferred TLS versions (drop old versions)
  minVersion: 'TLSv1.2',
  maxVersion: 'TLSv1.3',

  // Session reuse for faster handshakes
  sessionTimeout: 3600,

  handshakeTimeout: 30000
};

const server = https.createServer(options, (req, res) => {
  res.writeHead(200);
  res.end('OK');
});

server.listen(443);

Benefits of this configuration:
- Strong, modern ciphers reduce negotiation time
- TLSv1.3 is faster than TLSv1.2
- Session reuse avoids repeated full handshakes

6Enable connection pooling and reuse on the client

For client code making repeated requests, reuse connections with an HTTPS agent to avoid repeated handshakes:

javascript
const https = require('https');

const agent = new https.Agent({
  keepAlive: true,        // Reuse connections
  keepAliveMsecs: 30000,  // Keep alive timeout
  maxSockets: 50,         // Max concurrent connections
  handshakeTimeout: 30000
});

// Reuse agent across multiple requests
function makeRequest(url) {
  return new Promise((resolve, reject) => {
    https.get(url, { agent }, (res) => {
      let data = '';
      res.on('data', chunk => data += chunk);
      res.on('end', () => resolve(data));
    }).on('error', reject);
  });
}

// All requests reuse the same connection pool
makeRequest('https://api.example.com/endpoint1');
makeRequest('https://api.example.com/endpoint2');
7Check TLS certificate validity and chain

An invalid or incomplete certificate chain can cause handshake delays or failures:

bash
# Inspect your certificate details
openssl x509 -in server.cert -text -noout

# Verify the certificate chain is complete
openssl s_client -connect your-server.com:443 -showcerts

# Check for certificate warnings
curl -v --insecure https://your-server.com 2>&1 | grep -i cert

Ensure:
- Certificate is not expired (notAfter date is in the future)
- Certificate hostname matches your domain (check Subject Alternative Names)
- Intermediate certificates are included in the cert chain
- Certificate is signed by a trusted CA

Advanced notes

TLS Handshake Performance Optimization:
The TLS handshake involves multiple round-trips between client and server. With TLSv1.3, the handshake can be completed in a single round-trip for resumed sessions and 1-RTT for new connections. Ensure both client and server are using TLSv1.3 for best performance.

Session Resumption:
Implementing TLS session resumption (session IDs or tickets) allows clients to reconnect without a full handshake, significantly reducing reconnection time. Node.js handles this automatically if sessions are not explicitly disabled.

SNI (Server Name Indication):
If hosting multiple HTTPS domains on one IP, ensure SNI is properly configured. Misconfigured SNI can cause handshake delays or certificate mismatches:

javascript
const https = require('https');
const fs = require('fs');

const options = {
  SNICallback: (servername, cb) => {
    // Load appropriate cert based on servername
    const cert = fs.readFileSync(`/etc/ssl/${servername}.cert`);
    const key = fs.readFileSync(`/etc/ssl/${servername}.key`);
    cb(null, tls.createSecureContext({ cert, key }));
  }
};

const server = https.createServer(options);

Monitoring Handshake Performance:
Track handshake time with server events:

javascript
const https = require('https');

const server = https.createServer(options);

server.on('secureConnection', (socket) => {
  const handshakeTime = Date.now();
  console.log('Connection established', socket.getPeerCertificate());
});

server.on('clientError', (err, socket) => {
  if (err.code === 'ETIMEDOUT') {
    console.error('Handshake timeout detected');
  }
});

Platform-Specific Considerations:
On Windows, TLS handshakes can be slower due to certificate validation overhead. On Linux, ensure OpenSSL is up-to-date for better TLS performance. Docker containers should have sufficient CPU allocated to avoid handshake delays.

Frequently asked questions

What does "Error: TLS handshake timeout (connection timeout during TLS negotiatio" mean?
A TLS (Transport Layer Security) handshake timeout happens when the SSL/TLS connection negotiation between client and server doesn't complete within the configured timeout window. During the handshake phase, the client and server exchange cryptographic information, verify certificates, and negotiate encryption parameters. If this exchange takes longer than the timeout period, the connection is terminated with this error.
How do I fix "Error: TLS handshake timeout (connection timeout during TLS negotiatio"?
A TLS handshake timeout occurs when the client and server fail to complete the SSL/TLS negotiation within the timeout period (default 120 seconds). This typically indicates network delays, server resource constraints, or infrastructure issues.
What causes "Error: TLS handshake timeout (connection timeout during TLS negotiatio"?
Server is overloaded or under-resourced (CPU, memory), causing slow handshake processing Network latency between client and server is too high for the default timeout Firewall, proxy, or load balancer is intercepting or delaying the TLS handshake
Is the "Error: TLS handshake timeout (connection timeout during TLS negotiatio" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading