Power-Loss Protection
An SSD that acknowledges a write has made you a promise: that data is now durable, and it will survive a power cut. The entire stack above the drive — the filesystem journal, the database WAL, the fsync() your application blocked on — is built on the assumption that a completed write command means the bytes are safe. But inside the drive, the truth at the moment of acknowledgement is almost never that the data is on NAND. It is in a volatile DRAM write buffer, and the drive’s logical-to-physical map that knows where it went lives in DRAM too. Yank the power in that instant and, on a drive without proper protection, the acknowledged write evaporates and — far worse — the mapping metadata can be left torn, taking down data you wrote weeks ago. Power-loss protection is the small bank of capacitors and the carefully ordered firmware dance that turns that promise from a lie into the truth. This post is about what that machinery actually guarantees, what the marketing wording quietly excludes, and how to prove a drive does what its datasheet claims by cutting its power thousands of times and looking for the lies.
The reason this matters is that the failure mode is not “you lose the last second of writes,” which everyone expects and designs around. The dangerous failure mode is silent corruption of data you committed long ago, because the structure that maps your logical blocks to physical flash is itself the thing that got interrupted. A drive can pass every benchmark, every SMART check, and every casual yank test, and still scramble itself on the one power cut that lands inside the wrong microsecond. Understanding PLP means understanding which microseconds are dangerous and why.
What is actually volatile when the lights go out
To see what PLP protects, you have to know what is sitting in volatile memory at the moment of failure. There are three distinct things, and conflating them is the source of most confusion.
The first is in-flight user data: bytes the host sent that the controller has acknowledged (or is about to) but has not yet programmed into NAND. Modern drives buffer writes in DRAM both to coalesce them into full NAND program units and to return completion fast. If the host issued the write with a volatile write cache enabled and no FLUSH, that data is explicitly allowed to be in DRAM at acknowledgement time.
The second, and more important, is the logical-to-physical (L2P) map — the FTL’s address-translation table. As covered in the flash translation layer, every logical block address the host knows is indirected through this table to a physical NAND location, because the FTL relocates data constantly for wear leveling and garbage collection. The full map is large (roughly 1 GB of DRAM per 1 TB of capacity at 4 KB granularity), so the active, authoritative copy lives in DRAM. NAND holds only periodic checkpoints plus a journal of deltas. If power dies after you’ve moved data but before the map update reaches non-volatile media, the host asks for LBA 500, the table still points at the old physical page, and you read stale or garbage data — a lost write that the drive never reports as an error.
The third is other FTL metadata: the free-block lists, the program/erase counters that drive wear leveling, the bad-block table, and the open-block write pointers. Tearing any of these can brick the drive on the next boot, not just lose recent data.
At the instant of power loss
+----------------------------------------------------+
| DRAM (volatile) |
| - in-flight user writes (acked, not yet on NAND) |
| - active L2P map (authoritative copy) |
| - free lists, P/E counters, write pointers |
+----------------------------------------------------+
| must be flushed within
| the hold-up energy budget
v
+----------------------------------------------------+
| NAND (non-volatile) |
| - data pages + L2P checkpoint + journal/log |
+----------------------------------------------------+
A consumer drive with no capacitors and a DRAM-resident map has all three of these exposed. A DRAM-less consumer drive (using the Host Memory Buffer for its map) has moved the map into host RAM, which is even more volatile and disappears the instant the system loses power. The whole game of PLP is getting all three categories from the top box to the bottom box before the energy runs out.
The hold-up energy problem
When the input rail collapses, the drive does not stop instantly. A power-management IC (PMIC) watches the 12 V or 3.3 V input, and when it sags past a threshold it asserts a power-fail signal — often called PFAIL — to the controller. From that assertion the controller has a fixed energy budget, supplied by on-board capacitors, to enter “data hardening” mode: stop accepting new host commands, drain the write buffers, snapshot the L2P map, write a clean commit/log record, and quiesce. Everything has to complete before the rails fall below the controller’s minimum operating voltage.
The energy in a capacitor is the governing physics, and it is plain-text simple:
E = 1/2 * C * V^2 energy stored in a capacitor (joules)
Usable energy between a starting voltage Vfull and the
lowest voltage the regulator can still work from, Vmin:
E_usable = 1/2 * C * (Vfull^2 - Vmin^2)
Hold-up time for a given average power draw P:
t_hold = E_usable / P
The V^2 term is why you never drain a hold-up cap to zero — almost all the usable energy lives in the top of the voltage range. A bank held at 5.0 V that can operate down to 3.0 V delivers 1/2 * C * (25 - 9) = 8 * C joules; squeezing the floor down to 2.5 V only adds 1/2 * C * (9 - 6.25) = 1.375 * C more. A worked example: suppose a controller in hardening mode draws 1.5 W and you need 5 ms of runtime. That is 7.5 mJ. With a bank charged to 5 V and a 3 V cutoff:
C = 2 * E_usable / (Vfull^2 - Vmin^2)
C = 2 * 0.0075 / (25 - 9)
C = 0.0009375 F = ~938 uF
So you need on the order of a millifarad of capacitance, and that is before derating. Real designs budget two to four times that, because every capacitor technology loses capacitance over temperature, voltage, and age, and the energy must still be there after years of service in a hot chassis.
That derating is where the choice of capacitor chemistry becomes a real engineering trade-off, not a footnote:
| Capacitor type | Energy density | ESR | Voltage-bias C loss | Endurance / aging | Typical SSD use |
|---|---|---|---|---|---|
| Class-II ceramic (MLCC) | Low | Very low | Severe (can lose >50% C at rated V) | Excellent, no wear-out | M.2 drives, tiny banks, “metadata only” |
| Polymer tantalum | High | Low | Mild | Good, but failure mode matters | Enterprise U.2/E1.S hold-up banks |
| Aluminum polymer / electrolytic | Highest bulk | Moderate | Mild | Dries out, life halves per +10 C | Larger banks where board area allows |
The ceramic trap is the one that bites naive designs: a Class-II MLCC marked 47 uF at 0 V can collapse to under 20 uF when you actually bias it to its working voltage, so a bank sized from the nameplate is silently under-energy. Polymer tantalum is the enterprise workhorse because its capacitance is stable under bias and its ESR is low enough to deliver current fast, though designers still respect its historical short-failure mode by derating voltage hard. The Arrhenius rule that every 10 C of cooling roughly doubles electrolytic life is why a hold-up bank that is fine on the bench can fall below its energy budget after two summers next to a hot NAND package — and why serious firmware measures its own capacitor health at boot and flips the drive to a slower, cache-disabled mode if the bank has aged out.
What “power-loss protection” actually guarantees
Here is the part the datasheets are careful about. There are two fundamentally different things a vendor can mean by PLP, and the wording that distinguishes them is easy to skim past.
Full / enterprise power-loss protection means the drive will harden acknowledged in-flight writes in addition to its own metadata. With this, you may run with the volatile write cache enabled and skip FLUSH, and the drive still honours the durability contract: once a write completes, it survives a power cut. This is what lets enterprise drives post enormous low-latency fsync numbers — the flush is effectively free because the cache is already non-volatile by promise. In NVMe terms, such a drive may report that it has no volatile write cache (VWC) at all, so a FLUSH command is a no-op.
“Power-loss protection for data at rest” — the exact phrase Micron and others use on many client and even some datacenter drives — means something much narrower. It guarantees only that data already committed to NAND will not be corrupted by an in-progress operation when power is lost. It protects the FTL metadata and prevents a torn program from scribbling on top of existing data. It does not promise to save the acknowledged-but-buffered write that was in flight when the power died. Lose power mid-write on a “data at rest” drive and the last writes can vanish — that is considered correct behaviour, because they were never claimed to be durable without a flush. The drive comes back up clean and consistent; it just comes back up slightly in the past.
This distinction is not pedantry. If you assume a “data at rest” drive gives you enterprise durability and you disable barriers for speed, you have built a system that will silently lose acknowledged transactions on power loss while passing every consistency check, because the drive’s own state is always consistent. The corruption is in the gap between what your application thinks it committed and what the drive actually promised to keep.
| Guarantee | Consumer (no PLP) | “PLP for data at rest” | Full enterprise PLP |
|---|---|---|---|
| FTL metadata / L2P map survives intact | Not guaranteed | Yes | Yes |
| Existing at-rest data safe from torn writes | Not guaranteed | Yes | Yes |
| Acknowledged in-flight write survives cut | No | No | Yes |
| Safe to disable FLUSH/barriers for speed | No | No | Yes |
FLUSH honoured as a no-op (VWC off) |
No | No | Often |
The practical upshot for anyone building durable systems: if the drive does not advertise full PLP, you must keep filesystem barriers and fsync honesty turned on, exactly as you would for a spinning disk. This is also why a sane ZFS or filesystem design never trusts the drive blindly — see ZFS homelab storage that doesn’t lie for the same don’t-trust-the-hardware philosophy applied a layer up. PLP is a hardware optimization that lets you relax barriers; it is not permission to relax them by default.
FTL journaling and atomic flush on power-fail
Capacitors buy time; firmware spends it correctly. The mechanism that makes a power-fail flush atomic — all-or-nothing — is journaling, and it works just like a database write-ahead log. The FTL never tries to overwrite its mapping table in place. Instead it appends mapping changes to a journal in dedicated NAND service blocks, and periodically writes a full checkpoint. On a clean shutdown or a power-fail flush, the controller writes a commit record with a CRC that marks the journal consistent up to a point. On reboot, the drive replays the journal forward from the last good checkpoint up to the last valid commit record, and discards any trailing fragment whose CRC does not check out.
That last clause is the whole trick. Because recovery only trusts a journal entry once its CRC-protected commit record is fully on NAND, a power cut in the middle of writing a journal entry is harmless: the half-written entry has no valid commit, so replay simply ignores it, and the map reverts to its previous consistent state. The drive loses at most the operations after the last commit, never an inconsistent mix. This is the same logic that the LDPC/ECC machinery underneath assumes is intact — error correction (covered in ECC for flash, Hamming to LDPC) protects each page from bit rot, but it cannot save you if the map pointing at the page is torn. Journaling protects the structure; ECC protects the contents; you need both.
The power-fail flush sequence, in order, looks like this:
PFAIL asserted (rail sagging)
|
v
1. Stop accepting / completing new host commands
2. Finish or cleanly abort the in-progress NAND program
3. Drain volatile write buffer -> NAND (enterprise PLP only)
4. Append final L2P deltas to journal
5. Write commit record + CRC
6. Park: idle until rails decay
|
v
On next boot: replay journal to last valid commit, drop the rest
Steps 2 and 3 are where the energy goes, because a NAND program operation is slow — hundreds of microseconds to low milliseconds — and you may have several planes mid-program when the music stops.
The folding window: where it gets genuinely dangerous
The nastiest interaction is between PLP and the SLC write cache. To absorb bursts and to hit advertised write speeds, nearly all TLC and QLC drives write incoming data first into a region of flash operated in pseudo-SLC (pSLC) mode — one bit per cell, fast and robust — and later fold that data down into the dense TLC or QLC region in the background. The density endgame discussed in QLC, PLC and the density endgame makes this worse over time: the denser the target cell, the more fragile the program and the longer the fold takes.
Folding is a read-modify-write across multiple pages. To write three logical pages’ worth of data into one physical TLC wordline, the controller reads the pSLC sources, may combine them with neighbours, and runs a multi-pass program that walks the cell through several voltage distributions. Crucially, the destination TLC/QLC wordline is in an indeterminate state during the program — its old contents have been disturbed and the new contents are not yet final. If power fails in this window and the program does not complete, you can corrupt not only the data being folded but, on shared-wordline or paired-page geometries, adjacent already-committed pages on the same physical structure. This is the mechanism by which a power cut destroys old, settled data — the very thing “data at rest” protection is supposed to prevent, and the reason that protection is hard rather than free.
Robust firmware handles this by keeping the pSLC source copy valid and the L2P map pointing at it until the TLC program fully completes and verifies. Only then does the map atomically switch to the new TLC location and free the pSLC source. If power dies mid-fold, recovery finds the map still pointing at the intact pSLC copy and simply discards the half-written TLC wordline as garbage. The drive loses nothing, because it never trusted the destination until it was done. A cheaper or buggier implementation that updates the map optimistically — or that reuses the pSLC block too early — is exactly the kind of drive that the FAST ‘13 power-fault study found silently corrupting data. The physics of why these dense-cell programs are fragile under interruption is the same physics covered in NAND reliability physics and qual: partially programmed multi-level cells sit in voltage no-man’s-land and are the most likely to be misread.
How to actually test a PLP claim
You cannot verify any of the above from a datasheet. The word “protection” on a spec sheet is not a measurement, and the FAST ‘13 work demonstrated that drives advertising power-loss safety failed in practice — losing acknowledged writes, corrupting old data, and in some cases bricking. The only honest way to know is to cut the power, thousands of times, mid-write, and check for lies. This is a tractable bench project.
The principle. You write a stream of records to the drive where each record is self-describing — a monotonically increasing sequence number plus a CRC over its own payload — and you keep an independent host-side log of exactly which sequence numbers the drive acknowledged. You cut power at a random moment during the write loop. After the drive reboots, you read everything back and check three properties:
- No corruption of old data. Every record with a sequence number below the highest acknowledged-before-cut value must read back with a valid CRC and the value you wrote. A failure here is the catastrophic case — lost or scrambled at-rest data — and it should never happen on any drive claiming any flavour of PLP.
- No lost acknowledged writes (enterprise PLP only). Every record the host log says was acknowledged must be present. A failure here on a full-PLP drive breaks the durability contract. On a “data at rest” drive, losing the tail of acknowledged-but-unflushed writes is permitted — so you test this only when barriers were used or when the drive claims full PLP.
- The drive boots at all. A surprising number of cheap drives fail by not coming back, or coming back read-only.
The rig. A microcontroller drives a relay or MOSFET load switch on the drive’s power rail (3.3 V for M.2, 12 V for U.2). It must cut only the drive, while the host stays alive to detect the event and re-enumerate — so the device under test sits in an external enclosure or a hot-plug bay with its own switched supply, not in the host’s own boot path. A hard, fast cut (a MOSFET, not a slow relay bounce) matters, because a slow decay gives the drive’s own caps extra time and hides exactly the marginal designs you are hunting.
Host (stays powered) Arduino / RP2040
+-----------------+ +--------------+
| fio / test loop |---- USB --->| GPIO -> gate |
| + ack log |<-- "cut!" --| RNG timer |
+-----------------+ +------+-------+
| NVMe / SATA / USB | drives
v v
+-----------------------+ +-----------------+
| Drive Under Test |<-----| MOSFET / relay |<-- DUT power
| (external enclosure) | | on DUT rail ONLY| rail
+-----------------------+ +-----------------+
The loop, in pseudo-code, so the logic is explicit:
seq = read_highest_valid_seq_from_drive() # resume after each cut
while True:
payload = make_record(seq) # seq + CRC32(payload)
issue_write(payload, lba(seq))
if full_plp_under_test:
wait_for_completion() # ack = durable, by claim
else:
wait_for_completion(); fsync() # force a barrier
host_log.append(seq) # "drive said this is safe"
seq += 1
if random() < cut_probability:
signal_microcontroller_to_cut() # async power kill
# ... drive dies mid-loop, possibly mid-NAND-program ...
The microcontroller cuts at a random offset so that, across thousands of iterations, the kill lands at every phase of the write — including the dangerous fold window and the journal-commit window. After each cut, power the drive back up, re-enumerate, and run the verifier:
|
|
fio’s built-in --verify=crc32c with --verify_only is the cheap path: it writes verifiable patterns, and on a re-read after reboot it flags any block whose CRC does not match — directly catching property (1). For property (2) you need your own host-side acknowledgement log, because only you know what the drive claimed to have made durable. Run it for tens of thousands of cuts. A drive that survives a few hundred yanks but corrupts on cut number 4,000 is telling you its dangerous window is narrow but real — which is exactly the data you cannot get any other way. JEDEC’s JESD218 endurance methodology bakes an unexpected power cycle count into qualification for this reason; your rig is a small, honest version of the same test, run against the one drive model you are about to trust with a database.
One caution: a hard power-cut test stresses real hardware, and pulling the rail thousands of times can age the very capacitor bank you are testing. That is a feature — it tells you how the drive behaves as its hold-up energy degrades — but run it on a sacrificial sample, not the drive going into production.
Verdict
Power-loss protection is not a checkbox; it is a spectrum, and the words on the datasheet matter more than the logo. A drive with full enterprise PLP has earned the right to run with caches enabled and barriers relaxed, and it will turn your fsync storm into nearly free latency — that is the real performance reason these drives cost what they do. A drive that says “power-loss protection for data at rest” is making a much smaller promise: it will not corrupt your old data or brick itself, but it will happily drop the acknowledged writes that were in flight when the lights went out, and that is by design. Treat it like a barrier-honest consumer drive: keep fsync and filesystem flushes on, and never assume the cache is non-volatile.
For anyone choosing drives for a database, a journal, or a homelab NAS, the rule is simple. Read the exact PLP wording, not the marketing headline. If it does not say it protects in-flight acknowledged writes, it does not. And if the data is important enough that the answer matters, do not trust any of it — build the relay rig, cut the power ten thousand times, and let the drive prove with its own scars that it keeps the promise it made when it said your write was done. The capacitors and the firmware are an elegant machine, but elegance is not evidence. Power-cut testing is.
Sources
- Understanding the Robustness of SSDs under Power Fault — Zheng, Tucek, Qin, Lillibridge, USENIX FAST ‘13
- Reliability Analysis of SSDs Under Power Fault — ACM Transactions on Computer Systems (extended journal version)
- How SSD Power Faults Scramble Your Data — Tucek et al., Flash Memory Summit slides
- JEDEC JESD218B.01 — Solid-State Drive (SSD) Requirements and Endurance Test Method
- NVM Express NVM Command Set Specification 1.0a (Flush / FUA / VWC semantics)
- OCP NVMe Cloud SSD Specification (datacenter PLP requirements)
- Samsung White Paper: Power Loss Protection in SSDs
- Viking Technology — SSD Power Fail Protection Whitepaper (capacitor sizing, hold-up math)
- Kingston — SSD Power Loss Protection: How Hardware & Firmware PLP Prevent Data Loss
- Are SSD vendors cheating on FLUSH? — JonMichael Hands (on PLP and FLUSH semantics)
- Micron’s “Power loss protection for data-at-rest” — ServeTheHome forum discussion of the wording
- Planning for Sudden Power Failures with the MP5515 — Monolithic Power Systems (PFAIL, hold-up design)
Comments