Secure communication over HTTPS is powered by TLS (Transport Layer Security). In this post, we’ll explore:
- The TLS handshake step by step
- Performance impacts and optimizations
- Real-world examples and a visual diagram
❓ Why TLS Matters
The Problem with Plain HTTP
- Data in plaintext: Every header, URL, form field (including passwords) is exposed.
- Easy to intercept: Public Wi‑Fi or malicious network nodes can read or tamper with requests.
With TLS, your browser and server create a secure, encrypted tunnel, protecting confidentiality and integrity.
The TLS Handshake 🤝🏻 (Simplified)
Below is a diagram illustrating the core steps of a TLS 1.2 handshake. TLS 1.3 is similar but reduces round trips:

Handshake Breakdown
- ClientHello
- Announces TLS version, cipher suites, and random nonce.
- ServerHello + Certificate
- Server selects parameters and presents its X.509 certificate (with public key).
- Key Exchange
- Client encrypts a “pre-master secret” with the server’s public key.
- ChangeCipherSpec & Finished
- Both sides notify each other that future messages will be encrypted, then exchange integrity-checked “Finished” messages.
Once complete, all application data (HTTP requests/responses) flows through a symmetric cipher (e.g., AES), which is fast and secure.
⚡ Performance: Overhead and Optimizations
🕒 Latency Costs
- Full TLS 1.2 handshake: ~2 extra network round‑trips (100–200 ms).
- TLS 1.3 handshake: Only 1 RTT — significantly faster.
Key Optimizations
| 🔧 Technique | 🎁 Benefit |
|---|---|
| Session Resumption | Skip full handshake using session tickets |
| HTTP/2 + Keep‑Alive | Reuse one TCP/TLS connection for many requests |
| TLS 1.3 | Fewer round trips; optional 0‑RTT data |
| ECDSA Certificates | Faster cryptography than RSA |
| TLS Offloading/CDN | Hardware or edge servers handle encryption |
💻 Real-World Example: Enabling TLS in Rails
- Obtain a Certificate (Let’s Encrypt, commercial CA)
- Configure Nginx (example snippet)
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
}
}
- Force HTTPS in Rails
# config/environments/production.rb file
config.force_ssl = true
With this setup, Rails responds only over encrypted channels, and browsers automatically redirect HTTP to HTTPS.
📊 Measuring Impact
Run curl -w to compare:
# HTTP
✗ curl -o /dev/null -s -w "HTTP time: %{time_total}s\n" "http://railsdrop.com"
HTTP time: 0.634649s
# HTTPS
✗ curl -o /dev/null -s -w "HTTP time: %{time_total}s\n" "https://railsdrop.com"
HTTP time: 1.571834s
Typical difference is milliseconds once session resumption and keep‑alive take effect.
✅ Key Takeaways
- TLS handshake uses asymmetric crypto to establish a symmetric key, then encrypts all traffic.
- TLS 1.3 and optimizations (resumption, HTTP/2) minimize latency.
- Modern hardware and CDNs make HTTPS nearly as fast as HTTP.
- Always enable TLS for any site handling sensitive data.
🔗 Secure your apps today—HTTPS is no longer optional!