System designDeep dive11 min

Encryption in transit & at rest

Encryption in transit keeps data private while it moves; encryption at rest keeps it private while it sits on disks and backups. Each protects against specific attackers and not others, and both are only as strong as the handling of their keys.

1 · The map

Data is exposed while it moves, while it is stored and while it is used

A private journaling app has 2 million users writing daily entries, some with photos. One entry travels from a phone, through a load balancer, to an API server, into a database and object storage, and from there into nightly backups. Along that path it can be read in three different states:

PhoneLoad balancerAPI serverplaintext in memoryDatabase + backupsencrypted disksTLSmTLSTLSPhoneLoad balancerAPI serverplaintext in memoryDatabase + backupsencrypted disksTLSmTLSTLS

In transit, every hop is a separate encrypted connection. At rest, disks and backups hold ciphertext. In use, the API server must see the entry in plaintext to work with it, and storage or transport encryption can't help there.

Each kind of encryption answers a specific attacker, and none answers all of them:

Attacker

Example

What stops them

Someone on the network

Public Wi-Fi, a tapped link between data centers

Encryption in transit (TLS)

Someone holding the hardware

A disk pulled during maintenance, a lost backup

Encryption at rest

Someone with the app's access

A stolen admin login, an injection bug in the API

Not encryption at rest: the app decrypts for them. Access control (Authentication & authorization), field-level or end-to-end encryption

2 · In transit

TLS proves who the server is, then hides and seals everything after

TLS (Transport Layer Security), the S in HTTPS, gives a connection three properties:

  • Authentication: the server always proves its identity with a certificate; the client can too, but usually doesn't.
  • Confidentiality: only the two ends can read the data.
  • Integrity: any change in transit is detected.

TLS 1.3, the current version, completes its handshake in one round trip:

Each side contributes a fresh key share, and both derive the same session keys from them. Everything after ServerHello, including the certificate, is already encrypted.

Those key shares are generated fresh for every connection and thrown away afterward. That gives TLS 1.3 forward secrecy: if someone records the journal app's traffic today and steals the server's private key next year, the recordings stay unreadable, because the key never decrypted traffic, it only proved identity. TLS 1.3 removed static RSA and static Diffie-Hellman, so every full handshake has forward secrecy; resuming a session from a pre-shared key without a fresh key share, and 0-RTT early data, don't.

Two details deserve care:

  • 0-RTT resumption lets a returning client send data in its very first message, but that early data can be replayed by an attacker. Allow it only for requests that are safe to repeat (Idempotency).
  • Downgrade to plain HTTP. An attacker on the network can try to keep a user on unencrypted HTTP. The Strict-Transport-Security (HSTS) header tells browsers to use only HTTPS for the site from then on.

A certificate is a statement, signed by a certificate authority, that a public key belongs to a domain. Certificates now expire faster on purpose, which limits how long a stolen key stays useful and makes manual renewal impossible:

Public certificates, maximum until March 2026
398 days
Public certificates, maximum from March 2026
200 days
Public certificates, maximum from March 2027
100 days
Let's Encrypt, before its change
90 days
Public certificates, maximum from March 2029
47 days
Let's Encrypt, from February 2028
45 days

The browser and CA industry voted in 2025 to cut the maximum lifetime of public TLS certificates in steps: 200 days from March 2026, 100 from March 2027 and 47 from March 2029. At that pace, only automated renewal (the ACME protocol) is realistic.

3 · Inside

Encrypt inside the data center too, and let services prove who they are

A common setup ends TLS at the load balancer and sends plain HTTP to the servers behind it, on the theory that the internal network is trusted. That theory fails whenever anything inside is compromised, misconfigured or shared with other tenants, and the traffic between data centers often crosses links you don't own. The current practice, part of what's called zero trust (Network segmentation & zero trust), is to encrypt every hop and authenticate both ends.

Between services, that means mutual TLS (mTLS): both sides present certificates. When the API server calls the database proxy, each learns the other's identity cryptographically, not from an IP address that changes with every deploy (Service discovery & registration). Systems such as SPIFFE give each workload an identity like spiffe://journal.example/api and issue it short-lived certificates that rotate automatically.

Hop

Encryption

Identity checked

Phone → load balancer

TLS with a public certificate

Server only; the user authenticates inside the connection with a token

Load balancer → API server

mTLS with internal certificates

Both: only the balancer may call the API this way

API server → database

TLS, often mTLS

The database knows which service is connecting, not just which password

Region → region

TLS or an encrypted network link

Both ends of the link

Doing this by hand in every service is error-prone, which is one reason service meshes exist: a proxy beside each service performs mTLS and rotates the certificates, and the application talks plain HTTP to localhost. Either way, the certificates must be renewed automatically: an internal certificate that expires unnoticed breaks every call that depends on it.

4 · At rest

Envelope encryption keeps the master key inside a vault

Stored data is encrypted with a symmetric cipher, commonly AES-256 in GCM mode, which also detects tampering. The hard part is the key. If every journal entry were encrypted with one key stored next to the database, stealing the database would mean stealing the key too. And sending every entry to a key vault to be encrypted would be slow and limited by the vault's capacity.

Envelope encryption solves both. Each object or partition gets its own data key (DEK), which encrypts the data locally. The data key is itself encrypted ("wrapped") by a key encryption key (KEK) that lives in a key management service (KMS) backed by hardware security modules and never leaves it in plaintext:

The wrapped key is stored right beside the data; it is useless without the KEK. Every unwrap is a request the key service can refuse and record.

The design pays off in operations:

  • Rotation is cheap. A new KEK means re-wrapping small data keys, not re-encrypting terabytes.
  • Access is auditable. Reading data requires a logged call to the key service, which can be restricted to specific services.
  • Deleting a key deletes data. Destroying the key that wraps one user's data keys makes that data unrecoverable everywhere, backups included: crypto-shredding. Because that is irreversible, AWS KMS, for example, enforces a waiting period of 7 to 30 days before a deletion takes effect.

5 · The catch

Transparent encryption at rest stops thieves of disks, not thieves of access

Most cloud storage and managed databases now encrypt everything at rest by default, transparently: data is encrypted on its way to disk and decrypted on its way back. That defeats someone who walks off with a drive. It does nothing against someone who queries the database through the application, because the database decrypts for any authorized query, including one from an attacker holding stolen credentials. The deeper the encryption sits in the application, the more it protects and the more it costs:

Layer

Who can read plaintext

Protects against

Costs

Disk or volume

Anything running on the server

Stolen or discarded hardware

Almost nothing; on by default

Database (transparent)

Anyone who can query

Stolen data files and backups

Little

Field-level (the app encrypts chosen columns)

Only code holding the key

Database dumps, curious administrators

Little or no searching and sorting on those fields

End-to-end (the phone encrypts)

Only the user's devices

The provider itself, and anyone who breaches it

No server-side search or processing; lost keys mean lost data

The journal app has to choose for entries. End-to-end encryption means a breach of its servers exposes nothing readable, but it also means no server-side search, no recovery if a user loses every device and recovery key, and more work to share an entry. Apple's Advanced Data Protection shows the trade in practice: it end-to-end encrypts 25 categories of iCloud data and makes users set up a recovery contact or key first, while Mail, Contacts and Calendars stay outside it because the standards they must interoperate with don't support it.

A common middle ground is field-level encryption of the entry text with per-user data keys, plus transparent encryption for everything else. Entries stay unreadable in database dumps and to administrators, and deleting a user's key erases their journal, including every copy in backups (Disaster recovery & backups).

6 · In practice

The keys are the real security boundary

Encryption converts a data-protection problem into a key-protection problem. The rules that keep it solved:

  • Never put keys in code, images or config repositories. Keep them in a KMS or secrets manager and fetch them with the service's own identity.
  • Least privilege on decryption. Only the journal API may unwrap journal keys; analytics jobs get none.
  • Separate keys per environment, per region and, where it matters, per tenant or user.
  • Rotate on a schedule, and immediately on suspicion.
  • Plan for key loss as for data loss. Backups encrypted with keys that didn't survive the disaster are useless.

One threat changes the timeline. An attacker can record encrypted traffic today and wait for a quantum computer able to break today's key exchange: harvest now, decrypt later. Journal entries must stay private for decades, so this matters now.

The response is hybrid key exchange, which combines classic X25519 with the post-quantum ML-KEM, standardized as FIPS 203 in August 2024. By late October 2025, more than half of the human-initiated traffic Cloudflare sees already used it. Post-quantum certificates and signatures are less urgent and less mature, since forging a signature later can't reach back into recorded traffic.

  1. In transit

    TLS 1.3 everywhere, internal hops included; HSTS on public sites; automated certificate renewal; hybrid post-quantum key exchange where the stack supports it.

  2. At rest

    Default encryption on every disk, bucket, database and backup; envelope encryption with keys in a KMS.

  3. For the crown jewels

    Field-level or end-to-end encryption for the data a breach must never expose, accepting what it costs.

  4. Keys

    Least-privilege access, audit logs on every use, rotation, and a recovery plan for the keys themselves.

Check yourself

4 questions

1. A managed database encrypts its disks transparently. An attacker steals an admin's database credentials and runs SELECT * FROM entries. What do they get?
2. An attacker records a site's TLS 1.3 traffic for a year, then steals the server's private key. Can they decrypt the recordings?
3. Why encrypt data with per-object data keys wrapped by a KMS key, instead of sending all data to the KMS to encrypt?
4. A user asks the journal app to erase their account, including from backups that can't be edited. What makes that possible?

Takeaways

Remember this

  • Encryption in transit stops network eavesdroppers, encryption at rest stops hardware thieves, and neither stops someone using the application's own access.
  • TLS 1.3 authenticates the server, encrypts and seals traffic, and gives forward secrecy; use it on every hop, with mTLS between services.
  • Envelope encryption encrypts data with local data keys wrapped by a key that never leaves a KMS, making rotation, auditing and crypto-shredding practical.
  • Field-level and end-to-end encryption protect against breaches of the provider itself, at the cost of search, processing and key recovery.
  • Keys are the real boundary: keep them out of code, limit who can decrypt, rotate them, and start moving to hybrid post-quantum key exchange.