TLS session caching reduces the cost of repeated HTTPS handshakes by allowing clients to resume previously negotiated sessions. On busy Nginx reverse proxies and web servers, resumption lowers CPU spent on key exchange and certificate verification and improves latency for short-lived connections.
During the first TLS handshake, Nginx (via OpenSSL) negotiates ciphers, derives shared secrets, and issues session parameters that can be presented again on a later connection. With session IDs, the server must remember session state, so ssl_session_cache allocates a shared-memory zone that all Nginx worker processes can access for resumption.
The cache consumes RAM and is bounded by its zone size, so undersizing increases evictions and reduces resumption hit rate, while oversizing wastes memory. TLS 1.3 resumption primarily uses session tickets rather than a server-side cache, so ssl_session_cache matters most for TLS 1.2 and earlier clients. In load-balanced multi-node deployments, session ID resumption works only when the same node is reached, unless a ticket-based strategy with coordinated ticket keys is used.
Steps to enable TLS session caching in Nginx:
- Create a TLS session cache snippet under /etc/nginx/conf.d/.
$ sudo tee /etc/nginx/conf.d/tls-session-cache.conf >/dev/null <<'EOF' ssl_session_cache shared:SSL:10m; ssl_session_timeout 1h; EOF
shared:SSL:10m creates a 10 MB shared-memory zone shared across Nginx workers, and 1 MB stores about 4,000 sessions in typical configurations. Place the directives in http { } for a global default, or inside a TLS server { } block for per-site control.
- Test the Nginx configuration for syntax errors.
$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
A failing test prints the file path and line number for the first parsing error, and correcting that error is required before a reload can succeed.
- Reload the nginx service to apply the new configuration.
$ sudo systemctl reload nginx
On systems without systemd, a graceful reload can be triggered with sudo nginx -s reload.
- Save a resumable TLS 1.2 session to a temporary file.
$ openssl s_client -connect example.com:443 -servername example.com -tls1_2 -sess_out /tmp/nginx-tls-session.pem </dev/null CONNECTED(00000003) ##### snipped ##### New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256 ##### snipped ##### Verify return code: 0 (ok)
Forcing TLS 1.2 exercises ssl_session_cache directly, since TLS 1.3 resumption is ticket-based and does not rely on a server-side session ID cache.
- Repeat the connection using the saved session to confirm resumption.
$ openssl s_client -connect example.com:443 -servername example.com -tls1_2 -sess_in /tmp/nginx-tls-session.pem </dev/null CONNECTED(00000003) ##### snipped ##### Reused, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256 ##### snipped ##### Verify return code: 0 (ok)
If the output stays at New, common causes include the directives not being inherited by the TLS server block, a very small cache zone causing evictions, session timeout expiry, or a load balancer sending the second connection to a different Nginx node.
- Remove the temporary session file.
$ rm --force /tmp/nginx-tls-session.pem
The session file can contain resumption material and belongs in /tmp/ only for short-lived verification.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
Comment anonymously. Login not required.
