HTTPS traffic is growing, and backends are choking on TLS handshakes. Each new request requires asymmetric encryption — at 10,000 RPS, CPU shoots to 90% load. Instead of every upstream server wasting resources, we offload SSL termination to the load balancer. This is a standard practice described on Wikipedia. We set it up so certificates renew without downtime and clients see no errors.
Why SSL Termination Reduces Backend Load
SSL handshakes require expensive asymmetric operations. If each backend handles them independently, CPU overloads already at 10k RPS. Offloading to the load balancer reduces the load by 60–80% and simplifies certificate management: one domain — one certificate, not copies on every instance. The load balancer handles all encryption operations, while backends work over HTTP, further speeding up responses. CPU savings from SSL termination are especially noticeable under high load — you can save up to $2,000 per server annually on CPU costs.
What Problems Does SSL Termination Solve?
The most common problem is an incomplete certificate chain. The load balancer sends only the leaf certificate without the intermediate CA. The browser trusts it, curl is silent, but openssl s_client -connect example.com:443 -showcerts shows Verify return code 21 — unable to verify the first certificate. Mobile clients and older JDKs fail with 'PKIX path building failed'.
The second pain point is automatic Let's Encrypt renewal. Certbot renewed the certificate, but HAProxy didn't reload it without a restart — at 3 AM the site serves an expired cert. We solve this using Runtime API or reload signals without connection loss.
Checking the certificate chain
For diagnostics, use the commandopenssl s_client -connect example.com:443 -showcerts. If the return code is 21, combine the fullchain.pem, intermediate, and root certificates into one file. A check via SSL Labs will give an A+ rating.
How We Set Up SSL Termination for a Fintech Cluster
Recently we configured an HAProxy cluster for a fintech company: 20 domains, zero-downtime updates via Runtime API. Previously, each backend handled SSL independently — at 15k RPS, CPU was 90% loaded. After moving termination to the load balancer, load dropped to 25%, and SSL Labs rating reached A+. Certificates renew automatically via deploy-hook with zero downtime over six months of operation. As stated in the HAProxy documentation: Runtime API allows certificate updates without restarting the process.
Step-by-Step SSL Termination Configuration
- Choose a load balancer: nginx for simple projects (1–10 domains), HAProxy for clusters requiring zero-downtime.
- Generate a certificate: obtain fullchain.pem and privkey.pem from Let's Encrypt or a commercial CA.
- Configure: specify ssl_certificate, ssl_certificate_key, restrict protocols (TLSv1.2+TLSv1.3) and ciphers (ECDHE+AES-GCM).
- Test: check the chain, HSTS, X-Forwarded-Proto using testssl.sh and Security Headers Score.
- Auto-renewal: set up a deploy-hook to update the certificate without downtime.
nginx Configuration with SSL Termination
upstream backend {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
keepalive 32;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.fullchain.pem;
ssl_certificate_key /etc/ssl/private/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://backend;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}The X-Forwarded-Proto: https header is critical — without it, the application thinks it received an HTTP request and generates http:// links, breaking redirects and Mixed Content.
HAProxy with Automatic Certificate Renewal
HAProxy since version 2.2 can reload certificates without restart via Runtime API:
echo "set ssl cert /etc/haproxy/certs/example.com.pem << /etc/haproxy/certs/example.com.new.pem" \
| socat stdio /run/haproxy/admin.sock
echo "commit ssl cert /etc/haproxy/certs/example.com.pem" \
| socat stdio /run/haproxy/admin.sockThis allows integrating Certbot deploy-hook without downtime:
# /etc/letsencrypt/renewal-hooks/deploy/haproxy-reload.sh
cat /etc/letsencrypt/live/example.com/fullchain.pem \
/etc/letsencrypt/live/example.com/privkey.pem \
> /etc/haproxy/certs/example.com.pem
echo "set ssl cert /etc/haproxy/certs/example.com.pem << /etc/haproxy/certs/example.com.pem" \
| socat stdio /run/haproxy/admin.sock
echo "commit ssl cert /etc/haproxy/certs/example.com.pem" \
| socat stdio /run/haproxy/admin.sock Choosing Between nginx and HAProxy
When selecting a load balancer, consider complexity: HAProxy handles up to 1 million handshakes/s — 1.2 times faster than nginx on a weak CPU.
| Parameter | nginx | HAProxy |
|---|---|---|
| Configuration simplicity | High | Medium |
| Dynamic certificate update | Requires reload (graceful) | Runtime API (no loss) |
| TLS performance | ~90% of HAProxy | Reference (up to 1M handshake/s) |
| Multi-domain handling | Via server_name | Via SNI (requires setup) |
If you have 1–10 domains and want speed, use nginx. If you have a cluster of 100+ domains and zero-downtime is critical, use HAProxy.
Typical Mistakes and How to Avoid Them
- Incomplete chain: check with
openssl s_client -showcerts. If code 21 — combine fullchain + int + root. - HTTP→HTTPS redirect without HSTS: an attacker could perform downgrade attack. Add
add_header Strict-Transport-Security. - Missing X-Forwarded-Proto: application generates http links. Always forward the protocol.
- Manual certificate renewal: set up a deploy-hook immediately to avoid forgetting.
- No SSL Labs verification after deployment: target is A+ rating.
Our Work Process and Timelines
| Stage | Duration |
|---|---|
| Audit and requirements gathering | 2–4 hours |
| Architecture design | 1–2 hours |
| Implementation on staging | 4–8 hours |
| Testing (SSL Labs, curl, auto-renewal) | 2–4 hours |
| Production deployment | 1–2 hours |
| Scale | Timeline |
|---|---|
| Single load balancer, one domain | 4–8 hours |
| Multiple domains, wildcard | 1 day |
| HAProxy/nginx cluster + auto-renewal | 1–2 days |
What's Included in the Setup
- Audit of current load balancing scheme and certificates
- Design of optimum configuration (nginx/HAProxy, protocol selection)
- SSL termination setup with chain testing
- Integration of Let's Encrypt auto-renewal via deploy-hook
- Security verification: HSTS, X-Forwarded-Proto, Security Headers
- Complete documentation of configuration and procedures
- Training for on-call engineers (up to 2 hours)
- 2-week warranty support with remote assistance
With over 5 years of experience and 50+ successful projects, our team delivers reliable SSL offloading solutions. Get a consultation on SSL termination setup for your project — we'll assess your current scheme and suggest an optimal configuration. Contact us to discuss details.







