Start here: the stolen-disk threat#
TL;DRthe 30-second version
- Encryption at rest protects stored bytes β the ones sitting on a disk, in a backup, or in a database file. It answers one question: if someone gets the raw storage, can they read it?
- It is a different job from encryption in transit (TLS), which protects bytes moving over the network. You need both: TLS guards the wire, at-rest guards the storage. Neither covers the other's threat.
- Encrypting is cheap and solved β a fast, authenticated cipher like AES-GCM does it. The real problem is the key: a key stored next to the data it protects is useless, because whoever steals the data steals the key too.
- The standard answer is envelope encryption: a data key encrypts the data, and a separate key encryption key (held in a key management service) encrypts the data key. That split is what makes rotation, access control, and audit possible.
Most security effort defends the front door β logins, tokens, network rules. All of that assumes the attacker comes in through your application. Encryption at rest assumes they don't. It defends the case where someone holds the physical or logical storage directly: a disk lifted from a data center, a backup file copied to the wrong place, a cloud snapshot shared too widely, a stolen laptop. In that moment your access controls are bypassed, because the attacker is reading the bytes off the medium, not asking your server for them.
The obvious first idea is to lean on permissions: mark the file as readable only by the database user, lock the room, trust the cloud provider. That stops the polite attacker who goes through the operating system. It does nothing for the one holding the drive, because file permissions are enforced by the running OS β plug the disk into a different machine and they evaporate. So you need the data itself to be unreadable without a secret, no matter what machine it's plugged into. That secret is the encryption key, and turning readable data into ciphertext is what encryption at rest does.
How the bytes actually get encrypted#
The encryption itself uses a symmetric cipher: the same key encrypts and decrypts. Symmetric ciphers are fast β fast enough to encrypt every write and decrypt every read without anyone noticing β which is why they, not the slower public-key kind, do the bulk work of protecting stored data. The standard choice is AES, and specifically AES-GCM (Galois/Counter Mode).
GCM matters because it is authenticated. On top of the ciphertext it produces a short authentication tag β a fingerprint that only holds if the ciphertext was made with the right key and hasn't been altered. On decrypt, if a single bit of the ciphertext was flipped, the tag check fails and decryption refuses rather than handing back quietly-corrupted plaintext. So AES-GCM gives you two things at once: secrecy (an attacker can't read it) and integrity (an attacker can't tamper with it undetected). That is why it's the default for storage and for TLS alike.
Go deeperUnder the hood: why AES-GCM must never reuse a nonce
AES-GCM needs a nonce (a number used once) per encryption β a value that must be unique for every message encrypted under the same key. The nonce is not secret, just unique. It's usually 96 bits, per NIST's guidance in SP 800-38D. Reusing a nonce with the same key is catastrophic in GCM: it lets an attacker recover the internal authentication subkey and forge valid tags, and it leaks the difference between two plaintexts. This is a real production hazard, not a footnote β it's why you either use a random 96-bit nonce with a safe volume of messages per key, or a deterministic counter, and why you rotate keys before you approach the cipher's usage limits.
The key management problem#
Say you encrypt a 4-terabyte database with one AES key. Now name every place that key has to be. The database process needs it in memory to read and write. It probably sits in a config file or an environment variable so the process can load it on startup. That config is on the same server, and it's in your deployment system, and maybe in a backup of that server. You set out to protect one secret and you've made a dozen copies of it, several of them right next to the data they unlock.
That's the core tension. The key has to be reachable by the systems that use the data, but unreachable by an attacker who steals the data. A key in the same backup as the ciphertext protects nothing. And there's a second problem hiding behind the first: keys must change. A key might leak, an employee who saw it leaves, or a compliance rule says rotate every 90 days. But re-encrypting 4 terabytes to change one key is slow and risky β you'd have to decrypt and re-encrypt every byte you own. You need a design where the key can move far away from the data, and can be changed without rewriting the data. That design is envelope encryption.
Envelope encryption: two keys, not one#
Envelope encryption splits the one key into two, each with a different job. A data encryption key (DEK) encrypts the actual data β this is the fast AES-GCM key that touches every byte. A key encryption key (KEK) encrypts the DEK, and nothing else. The KEK never touches your data; its only job is to wrap and unwrap the small DEK. So instead of storing a bare DEK, you store the DEK encrypted by the KEK, sitting right next to the ciphertext it belongs to.
That flips the earlier problem on its head. The encrypted DEK next to the data is safe, because reading it requires the KEK β and the KEK lives somewhere else entirely: a key management service (KMS) or a hardware security module (HSM), a hardened system whose whole purpose is to hold keys and never let them leave. To read data, a server asks the KMS to unwrap the encrypted DEK; the KMS decrypts it and hands back the plaintext DEK, which the server uses in memory and then forgets. The one secret that never leaves the KMS is the KEK.
The payoff is rotation. Because the KEK only ever encrypts small DEKs, rotating it is cheap: unwrap each DEK with the old KEK, re-wrap it with the new one, and write back the tiny wrapped DEK β kilobytes of work, not terabytes. Your 4 terabytes of data are never touched, because the DEK that encrypted them didn't change. You rotate the outer key on a schedule and the data stays put. That is the entire reason envelope encryption exists, and it's why every major KMS is built around it.
Go deeperUnder the hood: the KMS 4 KB limit and GenerateDataKey
A KMS like AWS KMS won't encrypt large blobs directly β AWS KMS caps direct encryption at 4 KB, because sending terabytes through the service would be slow and would mean your data leaves your infrastructure. Instead you call an operation like GenerateDataKey: the KMS mints a fresh DEK and returns it twice β once in plaintext (use it now, in memory, then discard) and once wrapped by the KEK (store this next to your data). You encrypt locally with the plaintext DEK at full speed, keep only the wrapped copy, and the KEK never left the KMS. That single API pattern is envelope encryption in practice.
What rotation and access actually cost#
The whole point of the two-key split is that the expensive operation and the frequent operation are different keys. Encrypting bytes happens on every read and write, so it must be local and fast β that's the DEK, doing AES-GCM in your process with no network hop. Changing the master secret happens rarely and must be safe and audited β that's the KEK, living in the KMS. Put the numbers side by side and the design explains itself.
| Operation | Which key | Cost | How often |
|---|---|---|---|
| Encrypt / decrypt a record | DEK (local, in memory) | Microseconds β one AES-GCM call, no network | Every read and write |
| Unwrap a DEK on startup | KEK (in the KMS) | One KMS call, then cache the DEK | Rarely β per process / per key |
| Rotate the KEK | KEK | Re-wrap the small DEKs only β kilobytes | On a schedule (e.g. yearly, or on incident) |
| Re-encrypt all data (new DEK) | DEK | Read + rewrite every byte β terabytes | Almost never; only if a DEK is truly compromised |
Read the last two rows together, because that's the design decision. Rotating the KEK is cheap and routine β it never touches your data. Rotating the DEK means re-encrypting everything, which is the expensive job you built envelope encryption to avoid. So in normal operation you rotate the outer KEK often and leave the DEK alone. You only pay the terabyte-scale re-encryption if the DEK itself is exposed β the rare, genuinely-bad day. Matching the cheap frequent operation to the inner key and the expensive rare one to the outer key is the whole trick.
Where the encryption sits: three layers#
Encryption at rest can happen at three different depths in the stack, and the choice decides what it protects and what it costs you. Lower in the stack is simpler and covers everything blindly; higher up is more targeted but more work. Here's the trade laid out.
| Layer | What it encrypts | Protects against | The catch |
|---|---|---|---|
| Full-disk / volume | Every byte on the volume, transparently | A stolen physical disk or laptop | Useless once the disk is mounted and running β the OS sees plaintext, so a compromised host reads everything |
| Database (TDE) | The database files and backups | Stolen DB files, leaked backups, copied snapshots | The live database still returns plaintext to any query it authorizes β no defense against a SQL-level breach |
| Application / field-level | Chosen fields, before they reach the DB | A breached database, a curious DBA, a leaked backup β the data is ciphertext even inside the DB | You can't index or search an encrypted field normally; the app owns the crypto and the keys |
Full-disk encryption (like LUKS on Linux, or a cloud provider's default volume encryption) is the baseline β turn it on, it covers everything, and it costs you nothing to think about. But it only helps when the disk is off; a running server decrypts on the fly, so a live compromise sees plaintext. Database-level, often called Transparent Data Encryption (TDE), protects the files and backups the database writes, which shuts down the leaked-backup and stolen-snapshot cases. Application-level, or field-level, encryption is the strongest and the most work: your code encrypts specific sensitive fields β a card number, a medical note β before they're stored, so the data is ciphertext even to the database and to anyone who queries it.
PredictYou store users' medical notes. Full-disk encryption is already on. A read-only SQL injection bug leaks the notes table. Did encryption at rest protect the notes β and which layer would have?
Hint: Which layers decrypt automatically for an authorized query, and which one hands back ciphertext?
No, full-disk encryption did nothing here. The server was running, so the disk was already decrypted and the database returned plaintext rows to the injected query β full-disk only helps against a physically stolen, powered-off disk. Database-level TDE wouldn't have helped either, for the same reason: TDE decrypts transparently for any authorized query, and the injection rode in on an authorized connection. The layer that would have protected the notes is application- or field-level encryption: if your code encrypts the note field before storing it, the leaked table contains ciphertext, and the attacker needs the DEK (and therefore the KEK in your KMS) to read anything. The lesson is that lower layers defend the storage medium, not the running query path β the closer the threat is to your live application, the higher up the stack the encryption has to sit.
Choosing a layer β and encryption vs hashing#
Most systems don't pick one layer; they stack them. Full-disk encryption is close to free, so turn it on everywhere as a baseline. Add database-level TDE to cover backups and snapshots. Then reach for field-level encryption only on the truly sensitive columns β card numbers, health records, secrets β because it's the one layer that costs you something real at query time. The cost is searchability: an encrypted field is opaque bytes, so you can't do a normal WHERE lookup, a range filter, or an index on it. Encrypt the whole users table at the field level and you've turned your database into an expensive place to store blobs you can't query.
Go deeperUnder the hood: making an encrypted field searchable (and why it's dangerous)
There are ways to search encrypted data, and each trades away some secrecy. Deterministic encryption always maps the same plaintext to the same ciphertext, so you can do exact-match lookups (find every row where the encrypted email equals this encrypted value). But that determinism leaks: an attacker sees which rows share a value and can count and correlate them, even without decrypting. Randomized encryption (the safe default, what AES-GCM does with a fresh nonce) makes the same plaintext encrypt differently every time, so it leaks nothing β but you can't match on it at all. The rule of thumb: use randomized encryption everywhere, and only switch a specific field to deterministic when you truly need equality search on it and have accepted the leak.
Tokenization is a different escape hatch, common for card numbers. Instead of encrypting the value in place, you replace it with a random stand-in token and keep the real value in a separate, heavily-guarded vault. Your main systems only ever handle tokens, so a breach of them leaks nothing sensitive β the real data never lived there. It's not encryption at all; it's swapping the secret out for a meaningless reference, which shrinks the systems that ever touch the real value down to one.
In the wild
- AWS KMS, Google Cloud KMS, and Azure Key Vault are the managed key management services β they hold your KEKs, expose GenerateDataKey-style envelope operations, log every key use for audit, and back the highest tiers with hardware security modules.
- HashiCorp Vault's transit secrets engine offers 'encryption as a service': your app sends plaintext, Vault encrypts and returns ciphertext, and Vault holds and versions the keys β so application code never handles raw key material. Vault archives old key versions so old data still decrypts after a rotation.
- Transparent Data Encryption (TDE) ships in SQL Server, Oracle, and (via extensions or managed offerings) PostgreSQL and MySQL β it encrypts the database's files and backups without the application changing a line.
- LUKS is the standard full-disk encryption on Linux; cloud providers encrypt EBS volumes, persistent disks, and object storage by default, so 'encryption at rest' is often already on before you ask.
- An HSM (hardware security module) is a tamper-resistant device that generates and stores keys and does crypto inside its own boundary β the KEK is created there and provably never leaves, which is what regulated industries (payments, healthcare) require.
Pitfalls & gotchas
I turned on full-disk encryption. Isn't my data encrypted at rest now?
Against a stolen, powered-off disk, yes. But a running server has already decrypted the volume, so any process on that host β including an attacker who compromised it, or a leaked backup taken through the database β sees plaintext. Full-disk encryption is a baseline, not the whole story. If your threat includes a live breach or a leaked logical backup, you need database-level or field-level encryption on top.
Where should the encryption key live?
Anywhere except next to the data it protects. A key in the same server, config file, or backup as the ciphertext protects nothing, because stealing the data steals the key. Envelope encryption solves this: store the DEK wrapped by a KEK, and keep the KEK in a KMS or HSM that never releases it. The access-control question β who is allowed to ask the KMS to unwrap a key β is its own topic; see /auth for how a system decides who gets in.
If I rotate keys, do I have to re-encrypt all my data?
Not if you use envelope encryption. Rotating the KEK only re-wraps the small DEKs β kilobytes of work β and never touches the bulk data, because the DEK that encrypted the data is unchanged. You only re-encrypt the actual data if the DEK itself is compromised, which is rare. Rotating the cheap outer key often, and the expensive inner key almost never, is the point of the two-key design.
Why can't I just search my encrypted column like a normal one?
Because good encryption is randomized β the same plaintext encrypts to different ciphertext every time β so there's nothing stable to match on, which is exactly what makes it secure. You can force exact-match search with deterministic encryption, but that leaks which rows share a value. Encrypt at the field level only where you need the secrecy, and accept that those fields drop out of normal indexing and querying.
QuizA team stores the AES key for their encrypted database in an environment variable on the same server, alongside a nightly backup of both the database and its config. An attacker copies the backup. What did the encryption buy them?
- Full protection β the data is AES-encrypted, so it's safe.
- Nothing β the key was in the same backup as the ciphertext, so the attacker has both.
- Protection against network attackers only.
- Protection as long as the attacker doesn't know it's AES.
Show answer
Nothing β the key was in the same backup as the ciphertext, so the attacker has both. β The encryption bought them nothing, because the key traveled with the data. AES is strong, but a cipher only protects data when the key is somewhere the attacker can't reach; here the backup contained both the ciphertext and the key that unlocks it, so decrypting is trivial. This is the single most common real-world failure of encryption at rest: the key stored next to the data it protects. Envelope encryption exists precisely to prevent it β the stored DEK is wrapped by a KEK that lives in a KMS and never appears in a backup, so a copied backup is inert. 'It's AES' and 'nobody knows the algorithm' are both irrelevant; the whole game is where the key lives.
In an interview
When encryption at rest comes up, the weak answer is 'we encrypt the data with AES.' The strong answer is about keys, because that's where every real design and every real failure lives. Lead with the threat, then show you know the key is the hard part.
- Name the threat first: encryption at rest defends the stolen disk, the leaked backup, the copied snapshot β the case where the attacker holds the storage, not the application. Contrast it with TLS, which defends the wire; you need both.
- Say the cipher and move on: AES-GCM, symmetric and fast, authenticated so tampering is detected. That's one sentence β don't dwell, because it's the easy part.
- Spend your time on key management: a key next to its data is useless. Explain envelope encryption β a DEK encrypts the data, a KEK in a KMS/HSM encrypts the DEK β and why it makes rotation cheap (re-wrap kilobytes of DEKs, never re-encrypt terabytes).
- Place the encryption in the stack: full-disk (stolen hardware), database/TDE (leaked backups), field-level (a breached live database). Note the field-level cost β you lose normal search and indexing.
- Draw the line to hashing: passwords are hashed, not encrypted, because you never need them back β one-way versus reversible. Getting that distinction right signals you understand what each tool is for.
PredictAn interviewer asks: 'We're storing users' government ID numbers. Walk me through protecting them at rest.' What's a strong answer?
Hint: Which layer protects against a live breach, and how do you store the key so a leaked backup is useless?
Start with the threat and layer up. Full-disk encryption is the free baseline, but it only covers a stolen powered-off disk, so it's not enough for data this sensitive. Database-level TDE covers leaked backups and snapshots, which closes a big gap. But the ID numbers are exactly the case for field-level encryption: encrypt each ID with a DEK before it's stored, so even a breached live database or a curious DBA sees only ciphertext. Then handle the keys properly with envelope encryption β the DEK is stored wrapped by a KEK held in a KMS or HSM that never releases it, so nothing in the database or its backups can be decrypted without a KMS call you can audit and control. Mention the cost you're accepting: you can't do a normal indexed search on the encrypted ID, so if you need exact-match lookup you'd use deterministic encryption on that field and accept the small leak, or tokenize it. And rotate the KEK on a schedule to cap the blast radius, which is cheap precisely because it never touches the stored data. Naming the layers, the key design, and the searchability trade β not just 'we AES-encrypt it' β is what makes the answer strong.
References
- AWS KMS β Envelope encryption & data keys β The DEK/KEK model, the GenerateDataKey operation, and the 4 KB direct-encryption limit.
- Google Cloud KMS β Envelope encryption β A clear walkthrough of wrapping a DEK with a KEK and why it scales.
- HashiCorp Vault β Transit secrets engine β Encryption as a service: key versioning and rotation without the app touching key material.
- NIST SP 800-38D β GCM and GMAC β The authoritative spec for AES-GCM, including the nonce/IV rules and usage limits.
- OWASP β Cryptographic Storage Cheat Sheet β Practical guidance on ciphers, key management, and where encryption should sit.