Why storage is its own beast
Earlier in this rung we measured I/O by three numbers — throughput, latency, and dependability — and we learned to move data across a bus or a PCIe link using polling, interrupts, and DMA. Storage is the device on the far end of all that machinery, and it has a property memory does not: it is non-volatile. Pull the plug and DRAM forgets everything in milliseconds, but a non-volatile disk or SSD keeps your files for years. That permanence is the whole reason storage exists — and it is bought at a steep price in speed.
How steep? Recall the memory hierarchy: a register hit is a fraction of a nanosecond, an L1 cache hit a couple of nanoseconds, a DRAM access roughly a hundred. Storage lives several more rungs down. A modern flash SSD answers in tens of microseconds — a thousand times slower than DRAM — and a spinning hard disk in milliseconds, another hundred times slower again. Put plainly: if an L1 hit were one heartbeat, a disk seek would be a month-long expedition. That gulf is exactly why the operating system works so hard to keep your working data up in RAM and caches, touching storage as rarely as it can.
The hard disk: a record player chasing data
A hard disk drive is, almost literally, a tiny high-precision record player. One or more rigid platters spin thousands of times a minute, coated in a magnetic film, and a head on the end of a swinging arm reads and writes by sensing or flipping the magnetisation of tiny patches. Data is laid in concentric rings called tracks, each track divided into sectors (the smallest chunk you can read or write, historically 512 bytes, now usually 4096). To read a sector, the head must arrive at the right track and the right patch must rotate underneath it. Both of those are mechanical motions — and mechanical motion is glacial next to electronics.
So the time to fetch a sector breaks into three honest parts. First, seek time: swinging the arm to the target track, a few milliseconds on average because it depends how far the head must travel. Second, rotational latency: waiting for the spinning platter to bring the wanted sector under the head — on average half a revolution, which at 7200 rpm is about 4 milliseconds. Third, transfer time: actually streaming the bytes off once you are positioned, which is fast. Add the seek and the rotational wait and a single random read costs roughly 8 to 10 milliseconds before a single useful byte arrives. The processor could have run tens of millions of instructions in that window — which is precisely why a disk-bound program stalls.
Cost of one random 4 KB read from a 7200-rpm hard disk:
seek time ~ 4.0 ms (swing the arm to the track)
rotational latency ~ 4.2 ms (half a turn at 7200 rpm)
transfer time ~ 0.03 ms (stream 4 KB once positioned)
-----------------------------
total ~ 8.2 ms <-- before one useful byte
Sequential read (next sector already under the head):
no seek, no rotational wait -> ~0.03 ms per 4 KB
Random is ~250x slower than sequential. Layout is everything.The lesson hidden in that trace is that on a hard disk, where data sits matters enormously. Reading a megabyte laid out in one contiguous run is fast — one seek, then the head just lets the platter feed sector after sector under it. Reading the same megabyte scattered across the disk pays a fresh seek-and-rotate for every fragment and can be hundreds of times slower for identical data. This is the same locality story as caches, one level down: sequential access is the friend, random access the enemy, and a fragmented file or a database doing scattered lookups can crawl while the raw transfer rate sits idle.
The SSD: flash with no moving parts — and a catch
A solid-state drive throws away the platters and the arm entirely. It stores bits in flash memory: grids of cells that trap electric charge to remember a value with no power, and no mechanical part to wait on. That alone kills seek time and rotational latency, so an SSD answers a random read in tens of microseconds — a couple of hundred times faster than a disk — and, crucially, random access is nearly as fast as sequential, because there is no head to swing. This is why swapping a hard disk for an SSD makes an old machine feel reborn: every scattered little read that used to cost a seek is now almost free.
But flash hides a strange asymmetry that shapes everything about how an SSD behaves. You can read any page (a chunk of, say, 4 or 16 KB) freely. You can write a page only if it is blank. And here is the catch: you cannot blank a single page. Flash can only be erased a whole block at a time — a block being dozens or hundreds of pages, perhaps a few megabytes. So the rule is erase-before-write, and erase works at coarse granularity. To overwrite one 4 KB page in the middle of a full block, a naive drive would have to copy the whole block out, erase it, and write it back — a hugely expensive operation called write amplification. Flash also wears out: each block survives only a limited number of erase cycles before it stops holding charge reliably.
The flash translation layer: a quiet illusionist
If erase-before-write and wear were exposed raw, every program would have to be flash-aware and SSDs would be a nightmare to use. Instead, every SSD hides a small embedded computer running the flash translation layer (FTL) — firmware that presents the same simple 'read or write any sector' interface a hard disk offers, while doing something far cleverer underneath. Its central trick is indirection: it keeps a map from the logical sector numbers the operating system uses to the physical flash pages where the data actually sits, and it is free to move data around and rewrite that map whenever it likes.
Indirection solves both problems at a stroke. To 'overwrite' a logical sector, the FTL does not erase the old block; it simply writes the new data to a fresh, already-blank page somewhere else and updates the map to point there, marking the old page stale. This is exactly the address translation idea you met with virtual memory — a map from a clean logical view to a messy physical reality, letting the machinery underneath rearrange freely. Later, a background garbage collector reclaims blocks full of stale pages: it copies any still-valid pages elsewhere, then erases the whole block to make it writable again.
- The OS says 'write 4 KB to logical sector 5000', expecting a simple in-place update like a hard disk would do.
- The FTL ignores wherever sector 5000 used to live; it grabs the next free, already-erased page, writes the new data there, and marks the old physical page stale.
- It updates its logical-to-physical map so sector 5000 now points to the new page. The OS sees an instant overwrite; no block was erased on the critical path.
- Wear leveling spreads writes across all blocks so no single block is erased far more than the others, and garbage collection later erases blocks gone mostly stale to refill the free pool.
That fourth step names the last piece: wear leveling. Because every block tolerates only a finite number of erases, the FTL deliberately scatters writes so the wear is shared evenly — if it always reused the same handful of blocks, those would die while the rest stayed pristine, and the whole drive would fail early. Spreading the erases means the drive ages gracefully as one. The honest cost of all this cleverness is that an SSD's behaviour is hard to predict: a write may be instant, or it may stall behind garbage collection; and because the controller secretly relocates and reshuffles data, an SSD can wear and slow as it fills, in ways a simple disk never did.
Choosing, and the honest bottleneck
So which wins? Neither outright — they trade. SSDs crush hard disks on latency and on random access, draw less power, make no noise, and survive being dropped. Hard disks still win on cost per byte and, for now, on the very largest capacities, which is why archives, backups, and warehouse-scale 'cold' storage still spin platters by the million. A common design uses both: a fast SSD as a cache or for hot, latency-sensitive data, and cheap disks behind it for the bulk. The right answer is workload-driven — measure your access pattern, do not assume the newest technology automatically wins every axis.
Whichever you pick, hold on to the blunt truth from the start of this rung: for a great many real programs, I/O is the actual bottleneck, not the CPU. You can buy a processor twice as fast and see almost no improvement if your program spends its life waiting on storage — that is just Amdahl's law again, where the part you did not speed up dominates. Databases, web servers, file processing, and data analytics are routinely I/O-bound, which is exactly why so much effort goes into caching in RAM, batching requests, overlapping I/O with computation via DMA, and laying data out for sequential access.