When you open a site over plain HTTP, everything flying between the browser and the server is clear text. Anyone in the path (the owner of the café Wi-Fi, the ISP, a compromised router) can read it and even tamper with it: see your password, swap in their own page for the real one, cut a chunk out of the response. HTTPS closes that hole: the trailing "S" is the same HTTP, just wrapped in a protective TLS layer. Let's cover, in plain words, what TLS does, how two parties agree on keys, and why the browser trusts that the other end really is the site it claims to be.
Why encryption is needed
Protecting traffic has two separate jobs, and it helps not to mix them up.
The first is so no one eavesdrops. The data is encrypted, and a person in the middle sees not the request text but a meaningless pile of bytes. Your password, card number, and message contents stay private.
The second is so no one substitutes. Encryption by itself doesn't guarantee you're talking to the real server rather than an impostor who stepped in between you and is pretending to be the bank. TLS handles this too: it verifies the server's identity through a certificate and protects the data from being quietly altered in flight.
So TLS gives three things at once: confidentiality (nobody read it), integrity (nobody changed it), and authentication (it really is that server). Plain HTTP gives none of them.
Symmetric and asymmetric encryption, simply
To understand the handshake, you need to tell apart two kinds of encryption — using an everyday analogy with locks.
Symmetric encryption is one shared key. The same key that locked it also unlocks it. Fast and convenient, but there's a problem: how do you hand that key to the other party over an open network without it being intercepted along the way? If you send the key in the clear, the whole protection is pointless.
Asymmetric encryption solves exactly this problem. A party has a pair of keys: a public one and a private one. The public key can be handed to everyone — picture an open padlock you mailed out to everybody. Anyone can snap it shut on a box, but only you can open it with your private key, which you never give away. It's slow, but it doesn't require having a shared secret in advance.
TLS cleverly combines both: with asymmetric crypto the parties agree on a shared secret key, and then switch to fast symmetric encryption for the actual traffic. Asymmetric is used only to safely set up the shared key; everything else runs on the fast symmetric one.
The TLS handshake: agreeing on keys
The handshake is a short exchange of messages at the very start of the connection, before any real data flows. Its goal is to verify the server and produce a shared symmetric key. Step by step, without the crypto details:
- Client hello. The browser says: "I want a secure connection, here are the TLS versions and cipher suites I understand."
- Server hello + certificate. The server picks a suitable cipher and sends its certificate — it contains its name (the domain) and its public key.
- Certificate check. The browser makes sure the certificate is genuine, issued to the right party, and not expired (more on this below). If something's off — that's the scary red "your connection is not secure" page.
- Deriving the shared key. Using asymmetric crypto, the parties safely agree on a shared secret, from which a symmetric session key is born. Even if someone recorded the whole exchange, they can't compute that key from the outside.
- Switching to symmetric. From this point on, all HTTP traffic is encrypted with the fast symmetric key. The handshake is done; real requests start flowing.
All of this takes fractions of a second and happens invisibly every time you see the padlock in the address bar. Modern TLS 1.3 trimmed the number of steps so the connection is established even faster.
Certificates and certificate authorities
The key question from step 3 remains: the browser got a certificate with a public key, but how does it know this is the certificate of the real bank and not of an impostor who can also generate keys? Anyone can create keys.
The answer is certificate authorities (CAs). These are organizations that browsers and operating systems trust out of the box: a list of their root certificates is baked into the system. A CA verifies that you actually own the domain and signs your certificate with its signature. When the browser receives the site's certificate, it checks that signature: "signed by a trusted CA, the domain matches, not expired — I trust it."
This works as a chain of trust. The CA's root certificate is trusted by definition; it signs intermediate ones, and the intermediates sign your site's certificate. The browser walks the chain from the bottom up to a root it trusts. If even one link doesn't add up, trust collapses.
Certificates used to cost money and were issued by hand. Now there's Let's Encrypt — a free CA that issues certificates automatically. An important detail: its certificates live only 90 days, so they're renewed on a schedule by a dedicated client. The idea is that auto-renewal is more reliable than "issued for two years and forgotten."
TLS termination: where traffic gets decrypted
In a real system, TLS is almost never decrypted on the application itself. Between the internet and your service there's usually a load balancer or reverse proxy, and it's the one that decrypts incoming HTTPS. This is called TLS termination — "the point where TLS ends."
The typical setup: from the outside everything goes over HTTPS up to the balancer (nginx, a cloud load balancer, an ingress). The balancer holds the certificate, decrypts the traffic, and passes it on — to your service — as plain HTTP over the internal network. Your code then works with plain HTTP and doesn't think about certificates at all.
Why this is convenient: the certificate lives in one place instead of on every service; you only configure and renew encryption on the balancer; the application itself is simpler. The trade-off: the stretch between the balancer and the service runs unencrypted, so it must sit inside a trusted network. In higher-assurance environments the traffic to the service is encrypted too — but that's a deliberate choice, not the default behavior.
mTLS: mutual verification
In ordinary TLS only the client verifies identity: the browser makes sure the server is real, while it presents no certificate to the server itself (the user proves who they are later, with a password or token).
mTLS (mutual TLS) adds verification in both directions: not only does the client check the server, but the server also demands a certificate from the client. Both sides present their papers. For public sites this is overkill, but between services inside a system it's handy: service A accepts a request only if service B presented a valid client certificate. That way a neighbouring service proves it's one of ours before any business logic runs. It's one of the foundations of securing internal communication, worth returning to once you get to protecting services.
Where this applies
For a backend developer, TLS isn't abstract cryptography but a handful of very practical things.
- Where TLS is terminated. In a typical setup — on the balancer or ingress in front of the app; inside the cluster, services often talk over plain HTTP on a trusted network. You need to know this boundary to understand where the
X-Forwarded-Protoheader comes from and why the app "sees" http even though the user arrived over https. - An expired certificate is a common incident. Certificates have an expiry date, and a forgotten renewal takes the whole site down: browsers refuse to open the page. Hence the practice of auto-renewal and monitoring the expiry date — this is one of the most annoying and preventable outages.
- Self-signed certificates in tests. Locally and in test environments people often use a certificate they signed themselves, without a CA. The browser doesn't trust it and complains — which is fine for development. The main thing is not to carry the habit of "disable certificate verification" into production code.
Where beginners stumble:
- They confuse HTTPS with a separate protocol. HTTPS isn't a replacement for HTTP but the same HTTP inside a protective TLS envelope. All the methods, statuses, and headers are the same.
- They think TLS encrypts absolutely everything. The domain you connect to is still visible during the connection setup; what's encrypted is the content of the requests and responses, not the fact that "you visited such-and-such site."
- They assume encryption = authenticity. You can encrypt a channel with an impostor. It's the certificate and the CA that ensure the other end is the right server, not just "someone with keys."
- They disable certificate verification to "make it work." It quickly clears the error in a test and quietly kills all protection if it ships to production.
What to learn next
TLS sits on top of the transport layer, so it helps to understand what's beneath it. Start with the OSI and TCP/IP models to see which layer encryption lives on, and with TCP and UDP — TLS runs over a reliable TCP connection. Next, how connections work and why the handshake adds latency to every new connection. Come back to HTTP to nail down once and for all that HTTPS is the same thing in a protective envelope. And the bigger picture of securing services — certificates, secrets, access — is pulled together in the section on backend security.