Where Data Lives
Six easy pieces on storage, databases, and the art of choosing well
A first-principles guide that builds the entire idea of data storage from the physics of memory upward: through disks, file systems, the birth of the database, the invention of SQL, the distributed era, and finally a decision framework you can apply to any problem you will ever meet.
No prior database experience assumed. No jargon used before it is earned.
For builders, executives, decision-makers, and technical leaders
June 2026 · Reading time: about two hours
Contents
- How to Read This Book
- The Forgetting Machine
- Naming the Bytes
- The Era of Navigators
- The Declarative Turn
- When One Machine Is Not Enough
- The Art of Choosing
- Glossary
- Further Reading
BEFORE WE BEGIN
How to Read This Book
What this book promises, the method it uses, and the one lens you already own.
This book has a single goal: that by its last page, you can look at any problem statement, in any business, and answer three questions with confidence. Does this problem need a database at all? If it does, which kind? And why, in terms you could defend to an engineer on one side of the table and a CFO on the other?
That is a decision-making skill, and decision-making skills built on memorized product names rot quickly. The names change every two years. So this book takes the longer, sturdier route: we will build the entire idea of data storage from first principles, the way Richard Feynman built physics in Six Easy Pieces: starting from things you can verify yourself, deriving each layer from the failures of the layer below it, and never naming a concept before you have personally felt the problem it solves.
By the time the word “database” earns its formal introduction, you will have already invented most of one in your head. That is the point. A framework you derived is a framework you can trust under pressure; a framework you memorized is a slide you once saw.
The lens you already own
You already carry one tool that this entire book hangs on: the interface lens. Wherever two systems meet, they need one shared boundary. Between a human and a machine, that boundary is a user interface. Between one machine and another, it is an API: a contract that says what you may ask for and what you will get back, while hiding everything about how the answer is produced.
This book studies one specific, very consequential boundary: the one between a program that needs to remember things and the machinery that does the remembering. You will watch that boundary get invented, get placed badly, cause a decade of pain, and then get moved to the right place by one of the great ideas of computer science. The language that lives on that boundary today is called SQL, and we will see exactly why it won.
THE INTERFACE LENS
Keep this sentence nearby for the whole book: a good interface hides mechanism and exposes intent. Every chapter is secretly about where to draw that line for data.
Meet Aarav
Throughout the book you will follow Aarav, a founder building a small software product: a tool that helps teams diagnose where their workflows are broken. Aarav is not decoration. Every wall he hits is, almost beat for beat, a wall the entire computing industry hit between 1956 and today, usually with airlines, banks, or a moon landing on the line. History stops being trivia when you have just suffered the same failure yourself, sixty years later, in miniature.
The map
Six pieces, each one earning the next:
- The Forgetting Machine. Why computers cannot remember, and the physics that splits memory into fast-but-forgetful and lasting-but-slow.
- Naming the Bytes. A disk is just numbered blocks. We invent the file system from scratch, then discover its four walls.
- The Era of Navigators. The first real databases, built for Apollo and airline seats, and the hidden price of their design.
- The Declarative Turn. Codd’s idea, the birth of SQL, transactions, and the interface ladder from punched cards to plain English.
- When One Machine Is Not Enough. The web breaks the single computer; replication, sharding, CAP, the NoSQL families, and the modern data estate.
- The Art of Choosing. Question Zero, the Four Lenses, a default doctrine, and five worked problems solved end to end.
A fast path for the time-poor: read every shaded box and every table in Pieces 1 through 5, then read Piece 6 in full. You will get perhaps seventy percent of the value in a quarter of the time. The other thirty percent is the part that makes you dangerous in an architecture review, so come back for it.
PIECE ONE
The Forgetting Machine
Why computers cannot remember, and why the cure is slow.
AARAV’S DESK
Aarav ships the first version of his workflow-diagnosis tool. A user signs up, runs a diagnosis, gets a beautiful report. The next morning Aarav pushes a small fix and redeploys the server. He opens the app to admire his work, and it greets him like a stranger. Every user, every diagnosis, every report: gone. Nothing crashed. Nothing errored. The application simply forgot.
His first instinct is that this is a bug. It is not. It is physics. To see why, we have to open the machine.
A computer is two things
Strip away the keyboard, the screen, the network card, and a computer reduces to two essential parts: a part that computes and a part that holds. The processor is a worker that can do arithmetic and follow instructions astonishingly fast, but it can hold almost nothing in its hands. Memory is the workbench beside the worker: every number being added, every sentence being edited, every line of your running program sits on that bench while the work happens.
The bench in question is RAM: random access memory. “Random access” is an old term of praise. It means the worker can grab slot four million as quickly as slot one, in any order, no rewinding. RAM is gloriously fast. It is also, and this is the fact that just humiliated Aarav, completely amnesiac. Cut the power, even for a blink, and every slot reads blank.
When Aarav’s server redeployed, the hosting platform stopped his old process and started a fresh one. His users’ data had lived in Python variables, which is to say: on the workbench. New process, new bench, bare bench.
Why fast memory forgets
RAM’s amnesia is not a design oversight that some engineer could fix with effort. It follows from how the dominant kind of RAM physically works. A single bit of DRAM, the technology invented by Robert Dennard at IBM in 1968, is a microscopic bucket (a capacitor) that either holds a small charge of electrons (a one) or does not (a zero), guarded by one transistor acting as a tap.
Here is the catch: the bucket leaks. Electrons seep away in milliseconds. So the computer runs a permanent rescue operation, reading every bucket and topping it back up, thousands of times per second, forever. That refresh ritual is the price of DRAM’s speed and density. And it tells you instantly what happens when power disappears: no power, no refresh; no refresh, no charge; no charge, no data. Volatility is not a flaw in RAM. Volatility is RAM.
STOP AND THINK
Your phone keeps your photos through a dead battery, yet a document you never saved vanishes when an app crashes. Same device, two opposite behaviours. Before reading on: what does that tell you about how many kinds of memory the device must contain?
Why lasting memory is slow
To remember across a power cut, you need a physical mark that holds its shape with no electricity at all. Humanity has found two great tricks for this, and both are slower than the leaky bucket.
Trick one: magnetism. A hard disk drive (HDD) coats spinning platters with billions of microscopic magnetic regions; each region’s orientation is a bit, and a magnet does not care whether the power is on. The cost is mechanical. To read a particular bit, a physical arm must swing to the right track and then wait for the spinning platter (typically 7,200 revolutions per minute) to bring the right spot underneath it. Arms and platters move at the speed of metal, not the speed of electrons. A random read costs several milliseconds, which sounds tiny until you compare it to anything else in the machine.
Trick two: trapped electrons. Flash memory, developed by Fujio Masuoka at Toshiba in the 1980s, pushes electrons through an insulating wall onto a tiny island called a floating gate, where they stay stranded for years, power or no power. No moving parts, so a solid-state drive (SSD) answers in around a hundred microseconds: vastly faster than a disk arm, yet still roughly a thousand times slower than RAM, and each cell wears out a little every time you force electrons through that wall.
Notice the pattern. The physics that makes a mark permanent is exactly the physics that makes it slower to flip. Fast memory forgets because it is barely holding on; lasting memory lags because it is holding on hard.
FIRST PRINCIPLE
Fast memory forgets. Lasting memory lags. Every storage technology ever built sits somewhere on the line between those two sentences, and every system in this book, from the file system to the trillion-dollar cloud database industry, is a negotiation between them.
The hierarchy, at human scale
The numbers below are rough, and roughness is fine; what matters is the ratios. To feel them, use a trick: pretend one nanosecond is one second. The processor now lives at human speed, and the rest of the machine reveals itself.
| Where the data sits | Typical access | At human scale (1 ns = 1 s) | Survives power off? |
|---|---|---|---|
| Processor registers and cache | about 1 ns | one second: it is in your hand | No |
| RAM (the workbench) | about 100 ns | a minute and a half: walk to the shelf | No |
| SSD (flash) | about 100 µs | a bit over a day: courier from another city | Yes |
| Hard disk | about 10 ms | around four months: sea freight | Yes |
| Server in the same city | about 1 ms | roughly twelve days: parcel post | Someone else’s problem |
| Server across the world | about 150 ms | almost five years: a generation ship | Someone else’s problem |
Approximate access times for one piece of data. The exact figures drift with every hardware generation; the brutal ratios between rows do not.
Sit with that table for a moment, because half of database engineering falls out of it. If the durable copy of your data lives “four months away” and your processor lives “one second away,” then the entire game is: touch the slow thing as rarely, as predictably, and in as large batches as possible. Caches exist because of this table. Indexes exist because of this table. The reason your bank can answer in milliseconds while keeping your balance safe on disk is a sixty-year engineering campaign against this table.
A short history of remembering
Durable storage is older than the computer. It is worth thirty seconds of history, because two moments in it quietly set up everything that follows.
HOW IT ACTUALLY HAPPENED
Holes in card. In 1804 Joseph Jacquard controlled silk looms with punched cards: a hole meant lift this thread. In the 1880s a young engineer named Herman Hollerith borrowed the idea for data. The 1880 United States census had taken the better part of a decade to tabulate by hand; Hollerith’s punched-card machines chewed through the larger 1890 census in a fraction of the time. Each card was one record (one person), each hole position one field. His Tabulating Machine Company later merged into a firm that, in 1924, renamed itself International Business Machines. IBM was a data-storage company before it was a computer company.
Tape. The first commercial computers, like UNIVAC in 1951, kept data on magnetic tape: cheap, vast, and strictly sequential. To read the last record you spooled past every record before it. Tape made one kind of question cheap (“process everything, in order”) and every other kind brutal.
The jukebox. In 1956 IBM shipped the 305 RAMAC, whose disk unit stacked fifty 24-inch platters and stored about five megabytes. It weighed around a ton, moved by forklift, and leased for roughly $3,200 a month. Renting a single modern one-terabyte drive at RAMAC prices would run on the order of half a billion dollars a month. But the price was not the point. The acronym was: Random Access Method of Accounting and Control. For the first time, a machine could jump straight to any record without reading everything before it.
Hold on to the RAMAC moment. Random access changed which questions are affordable. On tape, “what is the balance of account 49,201?” costs a full spool; on a disk, it costs one hop, if (and this is the seed of the next chapter) you know where on the disk to hop to. The instant storage became jump-anywhere, somebody had to keep track of where everything was. That somebody is the subject of Piece Two.
AARAV’S DESK
Aarav now understands his disaster precisely. Nothing was wrong with his code; his data simply never existed anywhere durable. The fix sounds trivial: write it to disk. As we are about to see, “just write it to disk” is where the real story begins.
PIECE TWO
Naming the Bytes
We invent the file system from scratch, then run into its four walls.
A disk knows nothing
Here is a fact that surprises almost everyone the first time: a raw disk has no idea what a file is. It has never heard of folders, documents, photos, or names. A disk presents itself to the computer as one enormous row of numbered storage blocks (historically 512 bytes each, today usually 4,096), and it understands exactly two requests: read block number N, and write these bytes to block number N. That is the entire vocabulary.
Picture a notebook with two million numbered pages and no table of contents. You may write on any page and read any page instantly (that was RAMAC’s gift), but the notebook itself will never tell you what is written where. Now imagine handing that notebook to a team of people and asking them to keep a company’s records in it. Before anyone stores a single fact, you must answer some questions of pure bookkeeping:
- Names. How do we find “the Q3 report” again? Page numbers are addresses, not names, and humans think in names.
- Boundaries. Which pages belong to which document? A long report might span pages 4,512 to 4,907, and not necessarily consecutively.
- Free space. Which pages are blank and safe to use? Overwrite a used page and you have silently destroyed someone’s work.
- Organization. Ten documents need no system. Ten thousand need sections, and sections within sections.
STOP AND THINK
Stop here and actually design it. You have only the numbered pages themselves to work with: no sticky notes, no external ledger. How would you solve naming, boundaries, and free space using nothing but pages? Sketch an answer before reading on; the real one is close to whatever you just thought of.
Inventing the file system
The move every good answer converges on: sacrifice a few pages of the notebook to describe the notebook. Reserve, say, the first hundred pages as a master index. Each index entry records a name (“q3-report”), the list of page numbers holding its content, the total length, and perhaps a date. Keep one special page as a map of free pages. And for organization, the elegant trick: a folder is just another entry in the index whose content is itself a list of names. Folders containing folders gives you a tree, and suddenly “/finance/2026/q3-report” is a path you can walk.
Congratulations: you have invented the file system. Real ones differ only in engineering detail. Microsoft’s FAT (File Allocation Table, written in 1977 for Microsoft’s disk BASIC) is almost literally the reserved-index-pages design. Unix, around the same era, kept a small record per file called an inode holding its block list and metadata, with directories as ordinary files mapping names to inode numbers; the hierarchical tree itself was an idea Unix inherited from an ambitious 1960s system called Multics. Your laptop’s NTFS or APFS are descendants with decades of refinement, but the skeleton is the one you just derived.
FIRST PRINCIPLE
A file system is a small database with one table: names on the left, byte locations on the right. Every storage system you will ever meet is some elaboration of “reserve part of the medium to describe the rest of the medium.”
The first interface for data
Something quietly profound happened in that derivation. Programs no longer talk to the disk; they talk to the file system, through a tiny, stable vocabulary that has barely changed in fifty years:
open("/finance/2026/q3-report") -> a handle
read(handle, 4096 bytes) -> the next chunk
write(handle, bytes) -> appended or overwritten
seek(handle, position) -> jump within the file
close(handle)
Five verbs. Behind them, the operating system juggles block numbers, free-space maps, and platter geometry, and the program never knows. Swap the spinning disk for an SSD, reorganize every block on the device, and the program runs unchanged, because the contract it depends on says nothing about blocks.
THE INTERFACE LENS
This is the first machine-to-storage boundary in our story, and it is a well-drawn one: it hides mechanism (blocks, arms, free lists) and exposes intent (“the bytes called q3-report”). Hold the feeling of this clean boundary. In Piece Three we will watch an industry draw the next boundary in the wrong place, and pay for it for a decade.
What files do brilliantly
Files deserve respect before we expose their limits, because the limits are not defects; files were simply built for a different job. A file is universal: any program can read what any other wrote. It is simple: the mental model is “a named bag of bytes,” learnable in a minute. It is durable, portable, diff-able, version-controllable; this book’s own draft lives happily in files under git. Enormous, serious systems are built on nothing else. The question Piece Two turns on is not whether files are good. It is what happens when the bytes inside a file start to have structure that many people care about at once.
The four walls
AARAV’S DESK
Aarav applies the obvious fix to his amnesia problem. On every signup and every diagnosis, his server now writes everything into one file: data.json. Reads load the file, writes rewrite it. He redeploys; the data survives. He celebrates for exactly six days, which is how long it takes to hit all four walls.
Wall one: the simultaneous writers. Tuesday, 11:04 a.m.: two users finish a diagnosis in the same second. Both server requests read data.json, both append their own record to their in-memory copy, both write the whole file back. The second write lands a moment after the first and overwrites it. One user’s diagnosis silently vanishes; nobody errors, nobody is told. Files have no referee. The bytes belong to whoever writes last.
Wall two: the needle and the haystack. A user asks to see only her own past diagnoses. The file API offers “read bytes”; it has no concept of “records belonging to Meera.” So Aarav’s code reads the entire file (every user’s data) and filters in memory. At a hundred users this is invisible. At a hundred thousand, every page load is hauling a phone book through RAM to find one name. Recall the table from Piece One: the cost of touching the slow layer scales with how much of it you touch, and files only know how to be touched wholesale.
Wall three: nothing enforces the truth. A bug in Thursday’s deploy writes some diagnoses with user_id misspelled as userid, and a few pointing at users who were deleted last week. The file accepts all of it without complaint, because a bag of bytes has no opinions about its contents. The structure of Aarav’s data, and the rules that make it meaningful (“every diagnosis belongs to a real user”), exist only as good intentions scattered across his code. Every program that touches the file must re-implement those intentions, perfectly, forever.
Wall four: the half-written record. During one save, the server is restarted mid-write. The file is left containing the first half of a rewrite: syntactically broken JSON. The next read crashes the whole application for everyone. A file write is not all-or-nothing; the universe is allowed to stop it in the middle, and the file format has no way to even notice.
Write these four walls down somewhere, because they are the requirements document for everything that follows. A system that gives many simultaneous users safe, selective, rule-enforcing, all-or-nothing access to shared structured data: that system has a name, and we are now two chapters of honest suffering away from deserving it.
Files across the wire
One more thread to lay down before the 1960s. The instant two computers could talk over a network, the very first useful thing to do was move files between them. The protocol for it, FTP, was specified in April 1971 (RFC 114) by Abhay Bhushan, an IIT Kanpur graduate then at MIT, years before the internet’s modern plumbing existed. The lineage runs straight to the present: today’s cloud object storage (Amazon S3 and its peers, which we meet in Piece Five) is, at heart, the file reborn as a planet-scale web service: named bags of bytes, fetched over HTTP.
Notice what the network did to our interface story. “Where does the data live?” used to mean which blocks on this disk; now it can mean which machine on Earth. Every boundary we draw from here on may have a network in the middle of it, with that twelve-days-to-five-years latency from Piece One’s table riding along. Keep that in your pocket; it returns with force in Piece Five.
AARAV’S DESK
Aarav stares at his four walls and starts sketching workarounds: a lock file to serialize writers, one file per user to speed lookups, a validation script, a write-to-temp-then-rename trick for crash safety. Each patch is real, and each is a hand-rolled fragment of a database. Sixty years ago, the largest organizations on Earth stood exactly where Aarav stands now, except their version of the problem had airline seats, bank ledgers, and a moon landing attached. What they built next is Piece Three.
PIECE THREE
The Era of Navigators
The first databases, built for moon rockets and airline seats, and the hidden price of their design.
Sixty years earlier, the same four walls
Rewind to the early 1960s. Disks like RAMAC’s descendants exist; file systems exist; and the largest organizations on Earth are slamming into Aarav’s four walls at industrial scale.
American Airlines and IBM spent the years up to 1964 building SABRE, a system that let agents across the country book seats on the same flights in real time. Think about what that demands of storage: thousands of simultaneous writers (wall one), instant lookup of one flight among millions of records (wall two), an iron rule that a seat sold twice is a catastrophe (wall three), and bookings that must never be half-recorded (wall four). Banks faced the same list with money instead of seats.
And then there was the moon. North American Aviation, building the Apollo spacecraft, had to track a bill of materials running to millions of parts, where every assembly contained sub-assemblies, which contained sub-sub-assemblies, all revised constantly, and an error meant the wrong part in a vehicle carrying humans at 40,000 km/h. IBM’s answer, developed from 1966 and in production by 1968, was a system called IMS: by most accounts the first heavyweight database management system. It is not a museum piece, by the way; IMS still processes an enormous share of the world’s banking and airline transactions today, sixty years on. Storage systems, once trusted, are almost never retired.
Tree-shaped data: the hierarchical model
IMS made a deep design bet that mirrored its first customer’s problem: data is a tree. A rocket contains stages, stages contain engines, engines contain pumps, pumps contain parts. So in IMS you declared that hierarchy up front, and the system physically stored each parent with its children, making the natural question (“what is inside this assembly?”) almost free. The four walls were genuinely addressed: IMS refereed simultaneous writers, found records without scanning everything, enforced the declared structure, and (a topic we will give full honor in Piece Four) completed updates all-or-nothing.
The price was the shape of your questions. To ask IMS anything, a programmer wrote navigation commands against the tree:
GET UNIQUE segment=ENGINE where ENGINE_NO = 'E-204'
GET NEXT WITHIN PARENT segment=PUMP
GET NEXT WITHIN PARENT segment=PART
Read that as: walk to this engine, step down to its pumps, step through the parts under each. Beautiful, if the tree happens to be shaped like your question. But ask a question against the grain (“which assemblies, anywhere in the rocket, use bolt B-7741?”) and the tree offers no path; you crawl the whole structure. Worse: where does a part that belongs to two assemblies live? A tree allows one parent per child. Reality, inconveniently, is not a tree.
Web-shaped data: the network model
The fix for “one parent only” came from Charles Bachman, an engineer at General Electric, whose Integrated Data Store (early 1960s) let any record link to any number of others through named relationships. A part could be connected both to the assemblies using it and to the supplier providing it. Records and links formed a general web rather than a strict tree, and a 1969 industry committee, CODASYL, standardized the approach; for a decade this was the respectable mainstream of databases.
Bachman won the 1973 Turing Award, computing’s highest honor, and titled his acceptance lecture “The Programmer as Navigator.” He meant it proudly: the programmer was a ship’s pilot, steering record to record along the links, FIND the owner, GET the next member, follow the chain. The image was apt. It was also, though almost nobody could see it yet, the indictment.
The hidden price
Stand back and look at both models through the interface lens. What does a program need to know in order to ask a question? In IMS: the shape of the tree. In CODASYL: the layout of the links. In both cases, the boundary between “what I want” and “how it is stored” was drawn in the wrong place: the physical organization of the data leaked straight through the interface into every program ever written against it.
The consequences compounded silently. Suppose the business changes (it always does) and the data must be reorganized: a new level in the hierarchy, a link restructured for performance. Every program that navigated the old shape is now wrong, and there were thousands of them, in payroll, in billing, in reporting. Through the 1970s, large companies discovered that the majority of their programming budget was not building anything new; it was renovating old navigation code so it would not break when the data moved. The database had taken Aarav’s four walls and traded them for a fifth: paralysis.
THE INTERFACE LENS
You have seen this exact failure pattern in API design. An endpoint that exposes its internal table layout, so that every consumer breaks when the schema changes, is a leaky interface; the cure was a stable contract that hides the internals. The navigational databases were a planet-scale leaky interface. The question of the decade was where the boundary should have been drawn.
The question that changed everything
At IBM’s San Jose research lab sat a British mathematician named Edgar F. Codd, and in June 1970 he published a paper in Communications of the ACM with the gloriously dry title “A Relational Model of Data for Large Shared Data Banks.” Beneath the dryness was a question sharp enough to cut the whole era loose:
Why should the person asking a question have to know how the answer is stored?
A bank teller asking for an account balance does not specify which vault, which shelf, which folder. They name the account; the institution’s job is the route. Codd proposed that data systems owe their users the same courtesy: describe the data by its logical content only, ask questions in terms of that content only, and make the route entirely the machine’s problem. He called the gap this opened “data independence”: the freedom to reorganize the physical storage without breaking a single question.
It is hard to overstate how unwelcome this was. IBM’s revenue had an IMS-sized pillar in it, the performance engineers scoffed that no machine could pick routes as well as a human navigator, and Codd was, for several years, a prophet mostly without honor inside his own company. He was also right, in nearly every particular, and Piece Four is the story of his idea conquering the world.
STOP AND THINK
Before turning the page: Codd’s principle needs a data structure to stand on. If records may not point at each other (pointers are physical routes, the very thing we are banning), how could two pieces of data be related at all? What is the least mechanism that could possibly express “this diagnosis belongs to that user”? You already know the answer from spreadsheets.
PIECE FOUR
The Declarative Turn
Codd’s tables, the invention of SQL, the promise called a transaction, and the ladder of interfaces.
Tables all the way down
Codd’s construction is so familiar today that its radicalism hides in plain sight. All data lives in relations, which you may safely picture as tables: each table holds one kind of thing, each row is one instance of that thing, each column is one typed fact about it, and one column (or combination) is designated the primary key, a value that uniquely names the row: user number 4,012, order number 88,231.
Now the answer to the puzzle that closed Piece Three. How are things related, with pointers banned? By shared values, nothing more. A diagnosis row carries a user_id column containing 4012; the user row’s key is 4012; the relationship exists because the values match. Such a borrowed key is called a foreign key. If you have ever linked two spreadsheet tabs by a common ID column, you have built one with your own hands.
Feel how different this is from a link you must walk. A pointer is a route, fixed at write time, usable only in the direction it was laid. A shared value is a fact, and facts can be matched in any direction, in combinations nobody anticipated, years later. “All diagnoses by users who signed up in March, grouped by team” requires no pre-built path through the data; it requires only that the values be there. The relational model’s superpower is precisely this: it is the storage layout that does not bet on which questions you will ask.
| Hierarchical (IMS) | Network (CODASYL) | Relational (Codd) | |
|---|---|---|---|
| Data is shaped as | one tree, declared up front | records joined by explicit links | tables related by shared values |
| You ask by | walking parent to child | navigating link to link | stating conditions on values |
| Who finds the route | the programmer | the programmer | the system |
| A new kind of question | expensive or impossible | needs new links and code | just another query |
| Reorganizing storage | breaks the programs | breaks the programs | breaks nothing (data independence) |
Three answers to the same four walls. The third column is an interface decision as much as a data structure.
FIRST PRINCIPLE
Codd did not invent a faster database. He moved the boundary. Everything physical (layout, routes, ordering) went below the line, owned by the machine; everything logical (tables, values, rules) stayed above it, owned by you. Data independence is encapsulation applied to memory.
An interface for questions
A boundary needs a language spoken across it. Codd had proposed mathematically rigorous ones (a relational algebra and calculus), correct and complete and roughly as inviting to a business analyst as a tax form in Latin. The translation into something humans would actually type happened a few miles away, inside the IBM project assembled to test whether Codd’s theory could survive contact with real hardware: System R, begun in 1974.
Two researchers on that project, Donald Chamberlin and Raymond Boyce, set themselves an explicit design goal that should sound familiar to anyone who has shipped a product: the query language should be learnable by professionals who are not programmers. Planners, accountants, analysts: people with questions, not people with compilers. Their 1974 creation was SEQUEL, the Structured English Query Language, and its signature move was that a query reads as a description of the answer:
SELECT name, city
FROM customers
WHERE city = 'Bengaluru' AND signup_year = 2026;
Hold that against its navigational contemporary, the same intent in the era’s dominant style:
FIND FIRST customer-record OF city-set USING 'Bengaluru'
loop: GET customer-record
IF signup-year = 2026 THEN list name, city
FIND NEXT customer-record OF city-set
IF end-of-set GOTO done; GOTO loop
The first says what; the second says how, step by step, in a vocabulary married to the storage layout. Computer science calls the first style declarative and the second imperative, and the distinction is the entire ballgame: a declarative request leaves the machine free to find a better route tomorrow than it found today, without anyone editing the request.
Two footnotes from history, one sad and one absurd. Raymond Boyce died of a brain aneurysm in 1974 at age 26, weeks after presenting the language; the “B” in Boyce-Codd Normal Form, a cornerstone of database theory, is his memorial. And SEQUEL had to be renamed when a trademark surfaced, held by Hawker Siddeley, a British maker of fighter jets. The vowels were dropped, and the language that runs the world’s data has been SQL ever since (pronounce it either way; both camps are sure they are right).
THE INTERFACE LENS
Place SQL on the map you already carry. Between human and machine: a UI. Between machine and machine: an API. A database is a machine whose one job is remembering, and SQL is its API; but notice the genre difference. A REST API offers a finite menu of endpoints someone predefined. SQL is compositional: a small fixed vocabulary (SELECT, FROM, WHERE, JOIN, GROUP BY) that combines into effectively infinite questions, including ones nobody imagined when the data was stored. It is less like a restaurant menu and more like a grammar.
In a modern product the boundaries stack: browser → (UI) → frontend → (HTTP API) → backend → (SQL, over a wire protocol) → database. Three boundaries, one lens.
Who does the navigating now
Declarative is a luxurious promise, and someone still has to pay for it: if the programmer no longer plans the route, the database must. The component that does is called the query optimizer, and the blueprint for the modern kind was published in 1979 by Patricia Selinger and colleagues on System R. Given your question, the optimizer enumerates candidate routes (scan the whole table? use this index then join that way, or the reverse?), estimates each one’s cost using statistics it keeps about your data, and picks the cheapest. Bachman’s navigator was not abolished; it was hired by the database and ships inside the box, replanning every query, every day, as the data drifts.
The optimizer’s favorite tool deserves its own paragraph, because it will star in your decision framework later. How does any system find one row among a hundred million without reading them all? The same way you find a name in a phone book: the entries are kept sorted, so you can repeatedly halve the search. Databases generalize the trick into a structure invented around 1970 by Rudolf Bayer and Edward McCreight at Boeing, the B-tree: think of it as a phone book whose first page tells you which section to open, whose section page tells you which leaf page, three or four hops total even for billions of entries. Each hop is one touch of the slow storage layer from Piece One’s table, which is exactly why three hops instead of a hundred million is the difference between milliseconds and minutes.
FIRST PRINCIPLE
An index is a bet, not a free lunch. It makes chosen reads dramatically cheaper, and pays for that with extra work on every write (the index must be updated too) plus extra space. Read-heavy data wants many indexes; write-heavy data resents every one. File that away; it becomes a lens in Piece Six.
Promises under failure
AARAV’S DESK
Aarav, now happily on a relational database, adds paid plans. Upgrading a workspace is two writes: deduct the payment, raise the plan. One Friday a server dies between the two. Monday’s support inbox contains a customer who was charged and not upgraded, and Aarav discovers that the heart of a database is not how it stores data but what it promises about failure.
Work out, from scratch, what shared storage must promise for money to be safe on it. First: a multi-step change must be all-or-nothing; the universe may crash us mid-sequence, but the data must land as if the sequence either fully happened or never began. Second: the rules of the data (balances non-negative, every diagnosis owned by a real user) must hold at every visible moment, never “temporarily” broken in public. Third: a thousand simultaneous users must each see results as if they had the system to themselves; two purchases of the last seat cannot both succeed. Fourth: once the system says “done,” the change survives anything short of the building burning down, power cut included.
Bundle a group of operations under those four promises and you have a transaction. The promises themselves were given a name in a 1983 paper by Theo Härder and Andreas Reuter: Atomicity, Consistency, Isolation, Durability. ACID. The conceptual machinery underneath owes most to Jim Gray, who won the 1998 Turing Award for it. When an engineer says a system “has transactions” or “is ACID,” this paragraph is the entire content of the claim.
One implementation trick is too beautiful to skip, partly because accountants invented it five hundred years ago. How can “durable once confirmed” coexist with “the power may die mid-write”? Answer: never edit the books directly. First append the intended change to a journal (databases call it a write-ahead log), wait for the disk to confirm that the journal entry is safely down, and only then say “done” and update the main structures at leisure. If the crash comes early, the journal has no entry and the change never happened (atomicity); if it comes late, the journal replays the change on restart (durability). Every serious database, and every accounting clerk since medieval Venice, runs on write-ahead logging.
FIRST PRINCIPLE
A transaction is a promise kept across a power cut. When you evaluate any storage system, your sharpest question is never the benchmark; it is “exactly what do you promise when things fail, and when two actors collide?” Piece Six turns that question into a lens called Truth.
The race to ship
HOW IT ACTUALLY HAPPENED
IBM’s System R proved by the late 1970s that Codd’s model could perform, and then IBM hesitated, in no small part because the relational future competed with the IMS present. Meanwhile a 32-year-old named Larry Ellison read the System R team’s published papers, recognized the future when he saw it described in someone else’s footnotes, and with Bob Miner and Ed Oates shipped the first commercial SQL database in 1979: Oracle Version 2 (there was no Version 1; nobody buys a 1.0). The name came from a CIA project the founders had worked on. IBM followed with SQL/DS in 1981 and DB2 in 1983, and the race seeded an industry.
A parallel academic stream mattered just as much. At Berkeley, Michael Stonebraker’s Ingres project (mid-1970s) proved the model on ordinary minicomputers with its own language, QUEL; its successor project, begun 1986, was named for what it was: Postgres, “after Ingres.” Postgres adopted SQL in 1995, became community-run PostgreSQL in 1996, and is, half a century of compounding later, the database this book will keep recommending you start with. Stonebraker collected the 2014 Turing Award; relational databases have now earned four of them (Bachman, Codd, Gray, Stonebraker), which tells you how much of computer science this one problem contains.
Why did SQL, specifically, conquer? Four compounding reasons. It was declarative, so it aged well: applications survived reorganizations that would have killed navigational code. It rode the optimizer, which kept getting smarter beneath unchanged queries, a free performance dividend for decades. It was standardized early (ANSI in 1986, ISO in 1987), so skills and code became portable across vendors, creating a labor market that made choosing SQL the safe career and the safe procurement decision simultaneously. And it bundled the transaction promises, which is what let businesses trust it with the crown jewels. Network effects did the rest: today SQL is, by most measures, the most widely used programming language on Earth that most people do not think of as one.
The interface ladder
Step back and look at the whole climb, because seeing it as one ladder is what will let you place every future technology, including the AI-shaped ones, without being told where it goes.
| Rung | You express | What is hidden from you | Coupling cost |
|---|---|---|---|
| Physical (cards, tape) | the medium itself; card order is the program | nothing; you are the mechanism | total: change the deck, redo the work |
| Files (open/read/write) | named bags of bytes | blocks, platters, free space | structure inside the bytes is your problem |
| Navigational (IMS, CODASYL) | step-by-step routes through records | block management; not the layout | every layout change breaks every program |
| Declarative (SQL) | the shape of the answer | routes, layout, indexes, plans | near zero: data independence |
| Service (drivers, web APIs) | requests to a database that lives elsewhere | which machine, where on Earth | you inherit the network’s failures |
| Natural language (LLMs) | intent, in English | even the query language itself | you must verify what you can no longer see |
Each rung hides more mechanism and demands clearer intent. The lens never changes; only the altitude does.
Two rungs need a word. The service rung is simply the network from Piece Two arriving at the database: since the client-server era of the 1980s, the database is typically a separate machine you reach over a wire protocol, addressed by a connection string (Postgres famously answers on port 5432), through a driver library. Modern platforms stack a second service interface on top: Supabase, for instance, wraps a Postgres database and auto-generates a REST API straight from its tables, so the same data is reachable as SQL by your backend and as HTTP by anything else: two boundaries, one source of truth.
The top rung is the one your era added. Large language models now translate “show me last month’s churned customers by plan” into SQL on the fly, which makes plain English the newest interface to data, with the oldest rule still attached: the more the interface hides, the more precisely you must know what you mean, and the more deliberately you must verify what comes back. Feynman would recognize the trade instantly. So, by now, should you.
PIECE FIVE
When One Machine Is Not Enough
The web breaks the single computer, and an honest rebellion redraws the map.
AARAV’S DESK
Eighteen months on, Aarav’s tool is no longer a side project. Forty thousand teams run diagnoses, and every Monday at 9 a.m. they all open their dashboards at once. His single database machine, the faithful relational server from Piece Four, pins its processor at 100% during the spike and page loads crawl. He rents a bigger machine; it buys him one quarter of calm. He is about to live through the 1990s personally.
The arithmetic the web broke
For its first quarter-century, the database served a known audience: a company’s own clerks and analysts, hundreds of them, working office hours, running workloads someone had planned. The web inverted every term of that sentence. Now the users were the customers themselves, millions of them, worldwide, around the clock, and every single page load fired a handful of queries at the database. Success and load became the same number.
The 1990s answer was gloriously cheap. A free operating system, a free web server, a free language, and a free relational database (MySQL, released 1995) snapped together into the LAMP stack, and suddenly every two-person startup had the kind of data machinery that a decade earlier required an IBM contract. The model worked beautifully right up to its ceiling, and the ceiling was always the same component: the database, because it is the one part of the stack that holds state and therefore the one part you cannot simply photocopy. Web servers are stateless clerks; hire more and they neither know nor care about each other. The database is the single notebook they all share.
Up, or out
When one machine saturates, there are exactly two directions to go, and it is worth deriving their characters rather than memorizing them. Scaling up means buying a bigger machine: more processors, more RAM, faster disks. Its virtue is that nothing about your software changes; one notebook, just thicker. Its vices are a price curve that bends cruelly upward (twice the machine costs far more than twice the money) and a hard ending: there is always a biggest machine, and the biggest machine has a biggest.
Scaling out means more machines: ordinary, cheap, commodity boxes, cost rising roughly in a straight line. It is obviously where the curve says to go, and it carries one enormous, easily underestimated tax. The moment your data lives on two machines, there is a network between the pieces of your truth, and Piece One’s table told you what a network is: the slowest, least reliable layer in the entire hierarchy. Every guarantee Piece Four derived (one current value, all-or-nothing changes, a referee between simultaneous users) was quietly assuming a single machine. Scale out, and each of those guarantees must be re-earned across a wire that can stall, lie by omission, or go silent.
There are two basic moves, and every distributed database is some combination of them: keep copies of the data on several machines, or cut the data into pieces and give each machine one. The industry calls them replication and sharding. Each solves a real problem, and each breaks something you were relying on. Take them one at a time.
Copies: replication
The standard arrangement is modest and effective. One machine, the leader, accepts all writes. It already keeps a journal of every change (the write-ahead log from Piece Four, now earning its keep a second time): ship that journal, entry by entry, to one or more follower machines, which replay it and so hold a near-live copy. Now reads can be spread across the followers, which suits the typical application beautifully, since most read far more than they write. And when the leader machine dies at 3 a.m., a follower is promoted and the show goes on. Copies buy read capacity and survival.
AARAV’S DESK
Aarav adds two read replicas and his Monday spike flattens. Tuesday brings a strange bug report: a customer renamed her workspace from “Growth” to “Revenue,” the confirmation flashed, and the very next page load showed “Growth” again. Rename is broken, she says. It is not. Her write went to the leader; her next read went to a follower that was 300 milliseconds behind the news.
Sit with what just happened, because it is the first crack in something you have trusted all your life. The instant a second copy exists, the question “what is the current value?” has more than one defensible answer, separated by however far the journal shipping has fallen behind. That gap is called replication lag; it is usually milliseconds and occasionally, on a bad day, minutes. Engineers patch the worst symptom with rules like “a user’s own reads, right after her own write, must go to the leader” (read-your-own-writes), but the deeper lesson stands: copies turn “now” into a negotiation.
Pieces: sharding
Replication multiplies readers, but every copy still holds everything, so it rescues neither a write rate nor a data size that exceeds one machine. For that you must cut the data itself. Picture a library that has outgrown its building: put authors A through M on floor one and N through Z on floor two. Each floor is now half the size, half the crowd, twice the desks. In database terms each floor is a shard, and a small router consults the key (in practice usually a hash of it, to spread load evenly) to decide which floor any record lives on.
Now derive the costs, because they fall straight out of the picture. A question confined to one floor is cheap; that is the whole point. A question that spans floors (“every book published in 1970, any author”) means visiting every floor and merging the results: the scatter-gather, and it gets worse with every floor you add. A JOIN across floors is the navigator’s nightmare reborn at building scale. And a transaction across floors, “deduct on floor one and upgrade on floor two, all-or-nothing,” now requires two independent machines to promise in perfect unison across an unreliable wire; the protocol for it (two-phase commit) exists and is both slow and fragile, which is the polite way database people say “avoid.” Finally, resharding (the day floor one fills up and A through M must become A through F) is rebalancing a live library while readers are inside. Sharding works gloriously when your questions are shard-shaped: by user, by tenant, by time. It punishes everything else.
The theorem with no exit
One more derivation, the most famous in distributed systems, and you can do all of it in your head. Your data lives in two data centers, one in Mumbai and one in Frankfurt, kept as copies. Tonight a cable fails and the two halves cannot talk: a network partition, and at planetary scale these are a matter of when, not if. While the cable is down, a customer in Frankfurt asks to read a record. The Frankfurt machines have exactly two options. Answer from the local copy, knowing Mumbai may have accepted a newer write you cannot see: you stayed available and gave up the single truth. Or refuse (or wait) until contact resumes: you preserved the single truth and gave up availability. Search for a third option as long as you like; while the wire is cut, there is none.
That is the CAP theorem. Eric Brewer conjectured it in a July 2000 keynote; Seth Gilbert and Nancy Lynch proved it formally in 2002. It is routinely misquoted as “consistency, availability, partition tolerance: pick any two,” which makes it sound like a menu. It is not. On a real network, partitions are not optional, so the theorem says something sharper and smaller: when a partition happens, you must choose, consistency or availability, and you should have chosen on purpose, in advance, per system. The same lever exists in fair weather too, just relabeled: wait for the copies to confirm and you pay latency; answer immediately and you risk staleness. (Researchers call that extension PACELC; you can forget the acronym and keep the lever.)
FIRST PRINCIPLE
When data lives in two places, “now” becomes a negotiation. During a failure you choose between one truth everywhere and an answer everywhere; physics declines to provide both. A bank chooses truth and shows you a spinner. A social feed chooses answers and shows you a slightly old feed. Neither is wrong; each chose for its own cost of error.
STOP AND THINK
Classify these from your own life. Your banking app sometimes says “balance may not reflect recent transactions.” A group chat occasionally shows messages a few seconds out of order, then heals. An airline seat map freezes the seat the moment you start paying. For each: did the designers choose consistency or availability, and why does that match the cost of a wrong answer?
Scars, published
Through the 2000s the companies hitting these walls hardest were the ones whose ambitions were largest, and two of them did something unusual: they wrote down their scars as papers anyone could read.
HOW IT ACTUALLY HAPPENED
Google, 2003 to 2006. Indexing the whole web did not fit any machine money could buy, so Google built for fleets of cheap, frankly unreliable hardware and treated failure as weather, not catastrophe. Three papers shared the blueprint: the Google File System (2003), a file system spread across thousands of machines; MapReduce (2004), a way to compute over it; and Bigtable (2006), a giant sorted, sharded table for structured data, deliberately offering far less than SQL so that it could offer it at planetary scale.
Amazon, 2007. Amazon’s nightmare was different: during peak shopping, the cart must accept your item even if half a data center is on fire. Their Dynamo paper described an always-writable key-value store that takes the write somewhere, anywhere, and reconciles the copies afterward: availability chosen explicitly, eventual consistency named and embraced for a workload where a briefly stale cart is annoying and a rejected cart is lost revenue.
The rebellion gets a hashtag. Outside engineers turned the papers into open-source systems. At Facebook, Avinash Lakshman (a Dynamo co-author) and Prashant Malik fused Bigtable’s data model with Dynamo’s distribution to build Cassandra for inbox search, open-sourced in 2008. In June 2009 a San Francisco meetup of these new systems needed a short Twitter tag; organizer Johan Oskarsson’s “#nosql” stuck, and a heterogeneous collection of pragmatic trade-offs acquired, slightly to its own embarrassment, the name of a movement. The same year brought MongoDB, storing JSON-shaped documents, and Redis, a key-value store living in RAM.
Four families, one move each
“NoSQL” never named one idea; it named four or five, each best understood the same way: start from the full relational deal of Piece Four, deliberately give up one guarantee, and in exchange sharpen one superpower. Geometry, not ideology. Here are the families, each with its trade stated honestly:
| Family | Mental model | The superpower | What it gave up |
|---|---|---|---|
| Key-value (Redis, DynamoDB) | the index from Piece Four with nothing behind it: hand me a key, I hand you a value | absurdly fast lookups and counters at any scale; the cart that never says no | questions; it answers “by key” and nothing else |
| Document (MongoDB, Firestore) | the record and all its children in one JSON envelope | read or write a whole object in one touch; shapes can vary record to record and evolve freely | cross-document joins and (historically) multi-document transactions; duplication creeps in |
| Wide-column (Cassandra, Bigtable, Scylla) | one colossal sorted table, pre-cut into shards, writes accepted on any node | torrential write rates and time-ordered scans across continents; no single point of failure | ad-hoc queries; you must design the table per question, known in advance |
| Graph (Neo4j and kin) | relationships promoted to first-class citizens with their own storage | friend-of-friend, fraud rings, recommendations: questions that are five joins deep, asked in one hop | the easy tabular scans and aggregations relational systems eat for breakfast |
Every family is the relational model with one thing relaxed and one thing sharpened. Pick by the question you ask most, at the volume you actually have.
One marketing word from that era deserves a precise autopsy: “schemaless.” Document stores accept any shape without complaint, which feels like freedom, and you have already seen this movie. It is wall three of Piece Two returning in better clothes: the structure of the data did not vanish, it moved out of the database and into every program that reads the data, where it is enforced by hope. Engineers eventually coined the honest term, schema-on-read: the schema still exists, you have simply chosen to pay for it at read time, in code, per reader. That is a fine trade when one small team owns all the readers, and a quietly compounding debt as readers multiply.
Two kinds of questions
While the web was forcing the scale split, a second split was widening along a different axis: not how much data, but what kind of question. Watch a payment processor for a day and you see millions of tiny questions, each touching a few rows by key, each needing an answer now: the till. Watch the analytics team and you see a handful of huge questions, each scanning months of history to produce one chart, none caring about this second’s data: the back office. The industry named them OLTP and OLAP (online transaction vs analytical processing), and the deep insight is that they want opposite storage layouts, derivable straight from Piece One’s table.
A row store lays each record’s fields side by side on disk: perfect for the till, where “fetch order 49,201, all of it” is one touch of the slow layer. Now run an analytics question on it: “average order value by month, all hundred million orders.” You need two fields per record, but rows force you to haul every field of every record through the four-months-away layer to use two of them. Flip the layout: store each column contiguously instead, and that query reads only the two columns it names. Better, a column is a long run of same-typed, often-similar values (a million dates, a million amounts), which compresses brutally, ten to a hundred times, shrinking the cargo again. Columnar storage is why a warehouse scans a billion rows while you sip coffee, and why it is correspondingly clumsy at the till’s job of updating one record fast. Same data, opposite geometry, because opposite question.
| OLTP: the till | OLAP: the back office | |
|---|---|---|
| Typical question | fetch, insert, or update a few rows by key | scan millions of rows, aggregate into a summary |
| Who is asking | the application, thousands of times per second | an analyst or a dashboard, a few times an hour |
| Freshness needed | this very instant; money may be moving | today or this hour is usually fine |
| Layout that wins | rows together (grab the whole record in one touch) | columns together (read only what you ask, compressed) |
| Residents | Postgres, MySQL, the OLTP heart of every SaaS | BigQuery, Snowflake, ClickHouse; DuckDB on a laptop |
One company, two question shapes, two systems. The cardinal sin, which Piece Six will outlaw formally, is running back-office scans on the till.
The pendulum, and the absorbing giant
Stories about technology rebellions usually end with the empire falling. This one ends stranger: both sides won, by converging. From one direction, engineers missed transactions and SQL too much to stay away, and a “NewSQL” wave set out to rebuild relational guarantees on distributed bones. Its landmark is Google’s Spanner (2012), which wanted strict consistency across continents badly enough to install atomic clocks and GPS receivers in every data center, bounding the uncertainty in “now” tightly enough to order transactions worldwide. (When software hits a wall of physics, Google’s answer was: buy better physics.) CockroachDB carries the idea on in open source. The lesson is not the hardware; it is that the consistency-availability dial from this chapter is an engineering dial, not a religion, and with enough effort it can be pushed surprisingly far.
From the other direction, the boring default spent the same decade quietly annexing its rivals’ best reasons to exist. Postgres added JSONB (2014): real document storage, indexable, inside an ordinary column, transactions included. It has serious full-text search built in. PostGIS made it a first-rate geographic database; the Timescale extension handles time-series; and pgvector (2021 onward) stores the embedding vectors that AI applications search by similarity. The strategic consequence is large enough to preview Piece Six’s doctrine: every year, the boring choice covers more of the map, so the burden of proof on the exotic choice keeps rising.
Two quiet giants
Two systems from this era fit none of the dramatic narratives and matter more than most that do. The first is SQLite (D. Richard Hipp, 2000), which is not a server at all but a library: the entire database is one ordinary file, and the SQL engine runs inside your application’s own process. No network, no port, no administrator, no setup. It is, by deployment count, the most widely used database engine on Earth, sitting inside every phone, every browser, and most seat-back screens you have ever ignored. Whenever there is one application and modest concurrency, the correct amount of database server is often zero.
The second is Amazon S3 (2006), which is Piece Two’s file reborn as a planetary web service: named bags of bytes, any size, fetched over HTTP, engineered for durability so extreme it is quoted in elevens of nines. Object storage settled an old bad habit for good: large blobs (images, PDFs, video, model weights) do not belong inside your database, where they bloat backups and clog the cache; they belong in object storage, with the database keeping a pointer. Aarav’s diagnosis report PDFs are blobs. Into the bucket they go; a URL column stays behind.
The estate, assembled
Put the whole chapter together and the modern picture stops being one database and becomes a small, deliberate estate: a handful of specialized residences for data, each earned by a specific, measured pain. Here is the map; Piece Six supplies the discipline about when each box is earned rather than merely fashionable.
| Layer | Its one job | Typical residents | Earned when |
|---|---|---|---|
| System of record | the single authoritative truth; transactions, rules, the four walls solved | Postgres, MySQL | day one, the moment Question Zero (Piece Six) says you need a database at all |
| Blob shelf | large unstructured bytes: images, PDFs, video, model files | S3, GCS, R2 | the first user upload; the record system keeps pointers, never the bytes |
| Speed layer | memorized answers to repeated questions, served from RAM | Redis, Memcached | a measured hot read path the record system cannot serve cheaply enough |
| Find layer | fuzzy human search: typo-tolerant, ranked by relevance | Postgres full-text first; Elasticsearch, Typesense | real complaints about finding things, not before |
| Insight layer | heavy historical questions over months of data | ClickHouse, BigQuery, Snowflake; DuckDB | analysts’ scans start slowing the till, or get refused by it |
| Meaning layer | similarity search over embeddings: “find things like this” | pgvector inside Postgres; dedicated vector stores later | an AI feature over your own corpus, at vector counts that strain the default |
| Movement layer | events flowing reliably between all the boxes above | Kafka, cloud queues | several consumers need the same stream of events without losing any |
The modern data estate. Read the last column twice: every box is earned by a measured pain. A box with no pain behind it is decoration with an on-call rota.
AARAV’S DESK
Aarav’s whiteboard now holds this whole map, and he feels the familiar founder’s itch to build all of it, immediately, to be ready. That itch has bankrupted better-funded teams than his. The discipline he needs (which pains are real, which boxes are earned, and what to run until then) is not more technology. It is a decision procedure. That is Piece Six, and everything in the first five pieces was the price of admission to it.
PIECE SIX
The Art of Choosing
Question Zero, four lenses, a default doctrine, and five problems solved end to end.
Everything converges here. You have derived why memory splits in two, what files cannot promise, why the navigators lost, what SQL actually is, what failure does to a promise, and what each specialist family really trades. The framework you are about to receive is short, and its shortness is the point: it can be short because the foundations are deep. A person who memorized this chapter alone could recite it; only a person who earned the first five pieces can defend it in a room where someone is pushing back with a vendor deck.
The procedure has three movements. First, Question Zero: establish whether a database is needed at all. Second, the Four Lenses: Shape, Access, Truth, Scale, in that order, to characterize the problem. Third, the Default Doctrine: a deliberately boring default, plus a short table of measurable triggers, each of which earns exactly one specialist. That is the whole machine.
Question Zero: do you need a database at all?
The most expensive storage decision is the unnecessary one, because a database is not a thing you adopt; it is a thing you operate, back up, secure, migrate, and explain to every future hire, forever. So before any lens, run the data in question past four tests. They are exactly the four walls from Piece Two, turned into questions:
- Concurrent writers. Will more than one person or process change this data at the same time? (One person editing: a file is fine. A referee needed: wall one.)
- Unpredictable questions. Will you need to ask this data things you cannot list today? (Known, fixed lookups can be precomputed. Open-ended questions need a query engine: wall two.)
- Enforced rules. Are there invariants whose silent violation costs money or trust: balances, ownership, uniqueness? (Rules in code are intentions; rules in a database are law: wall three.)
- Survival of partial failure. Do multi-step changes need to be all-or-nothing even through a crash? (If a half-finished write is merely annoying, you may not need transactions: wall four.)
Zero or one “yes” answers, at small size, and you likely do not need a database yet. What you need instead sits on a ladder of less, and the professional move is to stand on the lowest rung that passes the tests:
- Nothing. Can the value be computed on demand, or simply not stored? The cheapest data is data you never keep.
- Constants in code. A pricing table with four rows changes by deliberate decision; it belongs in version control next to the logic that uses it, reviewed like any other change.
- Files in git. Content, configuration, this book’s own manuscript: one writer at a time, full history, free reviews, trivially portable. An astonishing share of “we need a CMS” is actually this rung.
- A spreadsheet. One non-technical owner, light collaboration, built-in UI, instant charts. Many internal “apps” are a spreadsheet plus self-respect.
- SQLite. Real SQL, real transactions, zero servers: the whole database is one file inside your application. For single-application tools, internal dashboards, and anything embedded, this rung carries shockingly far.
- A server database. The moment the four tests say yes in chorus (many writers, open questions, real rules, real failure cost), you have earned the rest of this chapter.
FIRST PRINCIPLE
The best database is the one you do not have to run. Every rung you climb adds operational weight you carry forever. Climb only when a test fails on the rung below, and write down which test it was; that sentence is the justification an architecture review will ask for.
The Four Lenses
Suppose Question Zero said yes. Resist the reflex to name a product; products are the last word in this procedure, never the first. Instead, characterize the problem through four lenses, in order. The order matters: each lens narrows the field the next one searches.
Lens 1: Shape. What is the geometry of the data?
Begin exactly where domain modeling begins: with nouns and the lines between them. List the entities (user, workspace, diagnosis, plan). Draw the relationships and their cardinalities (a workspace has many users; a diagnosis belongs to one workspace). The picture that emerges has a geometry, and geometry maps to family with very little ceremony:
- A web of distinct entities that reference each other, with rules riding on the references: relational. This is most business data, because businesses are made of relationships between things, and Piece Four built the entire relational model out of exactly this shape.
- Self-contained nested objects, read and written whole, whose internal shape varies or evolves per record: document. The envelope is the natural unit; tearing it into normalized tables would add joins with no payoff.
- Pure lookups: a known key in, an opaque value out, no other questions ever: key-value.
- The relationships are the data, and the questions hop across them: who connects to whom, through what, how many steps out: graph.
- An endless timestamped stream, queried by recent windows and aggregates: time-series geometry (a specialty Postgres handles via extension until volumes argue otherwise).
- Meaning itself: “find items like this one,” over embeddings: vector geometry, the newest room in the house.
Two cautions. Mixed estates are normal: a product’s core is almost always relational while one feature is vector-shaped and one log is time-shaped; the lens applies per dataset, not per company. And when the geometry is genuinely ambiguous, relational is the safe call, because it converts to anything later: a normalized schema can feed documents, caches, and warehouses, while the reverse journeys are expensive.
Lens 2: Access. What questions, how often, in what mix?
Two sub-questions, both already derived. First: do you know all the questions in advance? If tomorrow’s questions are unknowable (and for any product still discovering itself, they are), you need the compositional interface from Piece Four: SQL’s grammar, which answers questions nobody anticipated. Systems that demand queries be designed up front (wide-column especially) are only safe once a workload has stopped surprising you.
Second: what is the traffic mix? Estimate reads and writes per second, peak, honestly. Read-heavy data wants indexes spent generously, caching layers, read replicas; recall that an index is a bet that pays off on every read and is paid for on every write. Write-heavy data wants the opposite: few indexes, append-friendly structures, partitioning by time or tenant. Note carefully what this lens does not say: it does not say write-heavy data must leave the relational world. That refinement gets its own section below, because it deserves one.
Lens 3: Truth. What does a wrong answer cost?
Piece Five ended with a dial between one-truth and always-on. This lens sets the dial, and the setting is a business judgment wearing technical clothes: what does it cost when an answer is stale or two actions collide? Run the simultaneity test: can two actors act on the same scarce thing in the same moment? Two buyers, one seat; two withdrawals, one balance; two edits, one record. If yes, and the collision costs money or trust, you need transactions and strict consistency, full stop: the ACID promises of Piece Four are not optional garnish, they are the product. If instead a few seconds of staleness is harmless (a feed, a view counter, an analytics chart), you may trade truth for availability and latency exactly as Dynamo did, on purpose, in writing.
Lens 4: Scale. What are the actual numbers?
Scale is the lens people reach for first and should reach for last, because the previous three usually decide the family and this one merely sizes the deployment. Discipline here is numerical: write down five numbers before any architecture conversation. Total data today. Projected data in eighteen months (honest, not pitch-deck). Peak writes per second. Peak reads per second. Largest single table or object. Then hold them against reference points that surprise most newcomers: a single well-tuned Postgres node comfortably sustains thousands of transactions per second; with replicas and a cache in front, read rates go far higher; hundreds of gigabytes is routine and a few terabytes is fine; and cloud vertical headroom (the scale-up rung) is enormous before scale-out is even a conversation. Distribution is earned by sustained writes beyond a strong single node, by data that genuinely cannot fit, by a hard requirement for multi-region active-active service, or by regulators dictating geography. Until one of those is true in numbers, distribution is cosplay, and Piece Five itemized its price.
The write-heavy rule, sharpened
Practitioners carry pocket rules, and a common one goes like this: model the shape of the data first; then look at the read/write mix; lots of writes with few reads points away from relational toward unstructured or append-optimized stores, while moderate writes with heavy, complex reads points squarely at relational, typically Postgres, often via Supabase. As a pocket rule this is good, and it is worth seeing precisely why before sharpening it. Shape-first is exactly Lens 1, in the right position. And read-heavy workloads do favor relational machinery, because reads are where indexes, joins, and the optimizer pay their dividends.
Here is the sharpening, and it is one sentence: write volume alone never chooses a database; write volume combined with the cost of error and the complexity of questions does. The proof is the most write-heavy system you know: a bank’s ledger, hammered with writes all day, and the last data on Earth anyone would move out of a strict relational transaction. Writes did not eject it from relational, because Truth outvoted them. Write-heaviness only argues for leaving relational when it travels with two companions: a low cost of error (losing one event is noise) and key- or time-shaped questions (no rich ad-hoc queries on the raw stream). All three together, and the move is right. Writes alone, and it is a mistake wearing a benchmark.
| Workload | Writes | Cost of a wrong answer | Questions asked | Verdict |
|---|---|---|---|---|
| Bank ledger | heavy | a wrong balance is a crime | moderate, plus audits from any angle | relational, strict ACID; writes lose the vote |
| Clickstream telemetry | torrential | one lost click is statistical noise | aggregates, later, by time window | stream into columnar or time-series; the pocket rule’s home turf |
| Product catalog | light | mild (a stale price, briefly) | rich filters, joins, search | relational, indexed generously |
| Chat messages | heavy | order within a conversation matters; global truth does not | by conversation, recent first | document or wide-column, partitioned by conversation |
| Cart or session | moderate | losing one is annoying, not fatal | by key only | key-value, with the order of record landing in relational at checkout |
The sharpened rule in action: read each verdict as writes × truth × question-shape, never writes alone.
The Default Doctrine
Lenses characterize; a doctrine decides. Here is this book’s, stated plainly: start with Postgres, and stay until a lens forces an exit you can name and measure. The reasoning is the whole book compressed. Relational fits the shape of most business data (Lens 1). SQL answers the questions you have not thought of yet (Lens 2). Transactions deliver the strongest truth available (Lens 3). A single node’s honest capacity covers the actual numbers of almost every product that will ever be built (Lens 4). The model carries four Turing Awards’ worth of theory, fifty years of optimizer dividends, the deepest talent pool in software, and (Piece Five’s closing observation) an appetite for absorbing its rivals’ best features, so the default strengthens while you sleep.
On the service rung of the interface ladder, this book’s default wears a particular outfit: Supabase, which is Postgres operated for you, with authentication, row-level security, and an auto-generated API standing on top of the same tables. Nothing about the doctrine depends on that brand; everything depends on the engine underneath being boring, relational, and yours to leave.
Choose boring on purpose. Excitement in a database is a cost center; the interesting parts of your company should be above the data layer, not inside it.
“Until a lens forces an exit” is doing real work in the doctrine, so here are the exits, each phrased as a trigger you can measure. The discipline: a specialist enters the estate only when its row fires, and the row that fired gets written into the design document as the justification.
| Specialist | You have earned it when |
|---|---|
| Cache (Redis, Memcached) | monitoring shows a specific hot read path that the record system cannot serve cheaply enough, and you can state in writing how stale that answer may be (a number, in seconds). |
| Search engine (Elasticsearch, Typesense) | users measurably struggle to find things, and Postgres full-text (the free first step) has been tried and falls short on relevance, typo-tolerance, or speed. |
| Warehouse (ClickHouse, BigQuery, Snowflake; DuckDB for small) | analytical scans cover months of history, or analysts’ queries visibly slow the production till; the OLTP/OLAP split from Piece Five has arrived in your metrics. |
| Vector store (pgvector first; dedicated later) | an AI feature searches your own corpus by similarity; stay inside Postgres with pgvector until vector counts reach the tens of millions or filtering and latency demands outgrow it. |
| Wide-column (Cassandra, Scylla) | sustained write throughput genuinely exceeds a strong single node plus partitioning, and the questions are key- or time-shaped and enumerable in advance. |
| Graph database (Neo4j and kin) | multi-hop relationship questions dominate the workload and the equivalent SQL has become joins-of-joins that are both slow and unreadable. |
| Distributed SQL (Spanner, CockroachDB) | you need relational truth across regions or beyond one node, in numbers, and you have the team to pay the operational complexity this buys. |
Exit triggers. Note the recurring grammar: a measurement, then a tool. Never the reverse.
Five problems, solved end to end
Frameworks earn trust by being watched at work. Five problems follow, deliberately varied; for each, the lenses run in order and the verdict falls out. Read them actively: cover the verdict, run the lenses yourself, then compare.
A. Aarav’s product, chosen properly
Users, workspaces, diagnoses, plans, payments. Question Zero: many concurrent writers, unpredictable questions, hard rules (billing, ownership), real failure cost: yes, loudly. Shape: a web of entities and references; textbook relational. Access: unknown future questions (the product is still discovering itself), read-heavy mix. Truth: payments and plan changes fail the simultaneity test on purpose; strict transactions required. Scale: tens of thousands of users; a rounding error for one node. Verdict: Postgres via Supabase; report PDFs to object storage with a URL column; the auth and auto-API rungs come free. Exactly where Piece Four left him, now with the reasoning written down.
B. Product analytics: five million events a day
Every click, page view, and feature use, kept for two years, charted monthly. Shape: an append-only timestamped stream; nobody updates a click. Access: torrential writes, questions that are aggregates by time window. Truth: one lost event is statistical noise; nobody transacts against a click. Scale: five million rows a day is 1.8 billion a year: this number, finally, is real. Verdict: do not pour this into the till. Buffer events through a queue into a columnar or time-series home (ClickHouse; or Timescale to stay in the Postgres family), and let the product database stay lean. Note this is precisely the pocket rule’s home turf: heavy writes, cheap truth, time-shaped questions, all three companions present.
C. “Find similar past workflows”: an AI feature
Aarav wants diagnosis reports to surface similar past workflows across all tenants (suitably anonymized). Shape: meaning-similarity over embeddings: vector geometry. Access: moderate reads, modest writes as new reports embed. Truth: a slightly stale similarity list is harmless. Scale: a few hundred thousand vectors. Verdict: pgvector inside the existing Postgres. Same database, same backups, similarity joined to ordinary business data in one query. A dedicated vector store waits, per the exit table, for tens of millions of vectors that may never come.
D. Live leaderboard and sessions for a game
A million concurrent players, scores updating constantly, top-100 read every second. Shape: key-shaped (player to score) plus one sorted structure. Access: extremely hot, both directions. Truth: a leaderboard a second stale harms nobody; but if prizes pay out money, the final standings fail the simultaneity test. Verdict: Redis (its sorted sets were practically built for leaderboards) for the live layer; the moment money attaches, the authoritative results land in Postgres under a transaction. Two truths, two costs of error, two homes: the estate working as designed.
E. A marketing site and blog
Twenty pages, weekly posts, a contact form. Question Zero: one writer (the team, via pull requests), entirely predictable questions, no invariants, no transactional failure modes: four no’s. Verdict: no database. Markdown files in git, a static site generator, a hosted form service for the contact page (someone’s database, just not yours to run). The strongest answer in this chapter is the one that declines the question.
| Problem | What the lenses said | Choice |
|---|---|---|
| A. SaaS core (Aarav) | relational shape, unknown questions, strict truth, small scale | Supabase Postgres + object storage for blobs |
| B. 5M events/day analytics | time-shaped torrent, aggregate questions, cheap truth | queue → ClickHouse or Timescale; keep the till clean |
| C. Similarity feature | vector geometry, stale-tolerant, modest count | pgvector inside the same Postgres |
| D. Game leaderboard | key-shaped and hot; money only at the final step | Redis live; Postgres for the authoritative result |
| E. Marketing site | fails all four Question Zero tests | no database: markdown in git, hosted form |
Five problems, five different answers, one procedure. The framework’s value is not any single verdict; it is that each verdict comes with its reasons attached.
Anti-patterns: how this goes wrong
The same procedure, run in reverse, generates the industry’s most popular mistakes. Naming them is cheap insurance:
- Resume-driven development. The database is chosen because an engineer wants it on their CV. Detection: the justification names a technology before it names a measurement.
- Planet-scale cosplay. Adopting Google’s architecture without Google’s numbers, paying Piece Five’s distribution tax for traffic a laptop could serve. The essay title to remember: you are not Google.
- Blobs in the database. Images and PDFs stuffed into table rows, bloating backups and evicting hot data from cache. Pointers in the database; bytes in object storage.
- The database zoo. Six services, six different engines, each “best for its use case,” and an operations team drowning in six sets of backups, upgrades, and 3 a.m. failure modes. Consolidate on boring; diverge on triggers.
- Benchmark hypnosis. Choosing by a vendor’s millions-of-operations chart for a workload shaped nothing like yours. Your five numbers from Lens 4 outrank their marketing’s five million.
- Schemaless as not-thinking. Choosing document storage to avoid designing the data. Piece Five’s autopsy applies: the schema moved into every reader, it did not disappear.
- Analytics on the till. Month-long scans running on the production OLTP primary, slowing every customer to answer one analyst. The warehouse trigger exists precisely so this never has to happen.
The pocket card
Everything above, compressed to what fits in a head walking into a meeting:
THE WHOLE FRAMEWORK
0. Question Zero. Concurrent writers? Unpredictable questions? Enforced rules? All-or-nothing changes? Mostly no: stand on a lower rung (nothing, code, files in git, spreadsheet, SQLite).
1. Shape. Model the domain first. Entities and references: relational. Self-contained evolving envelopes: document. Key-in, value-out: key-value. Relationship-hopping: graph. Timestamped torrent: time-series. Similarity: vector.
2. Access. Unknown future questions need SQL’s grammar. Read-heavy: spend indexes, add replicas and cache. Write-heavy: spend fewer indexes, partition; and remember writes alone never decide.
3. Truth. Run the simultaneity test. Collisions that cost money or trust: strict transactions. Harmless staleness: you may trade truth for availability, deliberately, in writing.
4. Scale. Write down five real numbers before any architecture talk. One tuned Postgres node: thousands of transactions per second, terabyte-class data. Distribute only when the numbers, not the nerves, demand it.
Default: Postgres (Supabase when you want auth and an instant API on the service rung). Exit only on a measured trigger, and write the trigger down. Blobs to object storage, always. One system of record. When in doubt: boring and reversible.
The whole book in ten sentences
- Fast memory forgets and lasting memory lags, and every storage system ever built is a negotiation across that gap.
- A disk is just numbered blocks; a file system is the part of the disk that spends itself describing the rest.
- Files hit four walls: no referee for simultaneous writers, no selective questions, no enforced rules, no all-or-nothing writes.
- The first databases answered with hand-navigated routes, and coupled every program to the data’s physical layout.
- Codd moved the boundary: declare the shape of the answer and let the machine find the route; SQL is that boundary, standardized.
- A transaction is a promise kept across a power cut: atomic, consistent, isolated, durable.
- The web outgrew one machine, and copies plus pieces forced a standing choice, during failures, between one truth and always-on.
- The NoSQL families are honest specializations: the relational deal with one guarantee relaxed and one superpower sharpened.
- Choose through four lenses, Shape then Access then Truth then Scale, and only after Question Zero: do you need a database at all?
- Default to boring relational, and let measured pain, never fashion, buy each specialist into the estate.
AARAV’S DESK
Aarav ships on Supabase. The PDFs live in a bucket; the analytics stream waits, unbuilt, for the day the till slows; pgvector sits one migration away. On Friday he redeploys at 6 p.m., which once would have been an act of pure recklessness, and goes home. The machine still forgets everything every time the power blinks. He no longer does, and that, in the end, was the entire problem to solve.
That is the book. The products in these pages will age; some already have between drafting and your reading. The derivations will not, because physics does not refactor and the four walls are not going anywhere. When a new database arrives next year wearing a remarkable benchmark, you now own the only three questions that matter: where does it sit on the interface ladder, what does it promise when things fail, and which measured pain of yours, exactly, is it the trigger for? Ask those, and you will be the calmest person in the room.
BACK MATTER
Glossary
Every term this book earned, defined in one breath each.
| Term | In one breath |
|---|---|
| ACID | the four transaction promises: atomic (all-or-nothing), consistent (rules never visibly broken), isolated (simultaneous users cannot corrupt each other), durable (confirmed means survives a crash). |
| B-tree | the phone-book structure behind most indexes: sorted, shallow, finding one row among billions in a few hops. |
| Block | the disk’s native unit: a numbered, fixed-size chunk of bytes, the only thing raw storage understands. |
| Cache | a fast layer that memorizes answers to repeated questions, trading possible staleness for speed. |
| CAP theorem | during a network partition, a distributed system must choose between consistency (one truth) and availability (always answering); proven 2002. |
| Columnar storage | laying each column contiguously on disk so analytics read only the fields they ask for, heavily compressed. |
| Connection string | the address and credentials a program uses to reach a database server over the network. |
| Data warehouse | a columnar home for historical, analytical questions, kept separate from the transactional till. |
| Database (DBMS) | a system giving many simultaneous users safe, selective, rule-enforcing, all-or-nothing access to shared structured data. |
| Declarative | stating what answer you want and letting the system plan how; SQL’s defining property. |
| Document store | a database whose unit is a self-contained nested object (typically JSON), read and written whole. |
| Eventual consistency | the promise that copies will agree, eventually; reads meanwhile may be briefly stale. |
| File system | the part of a disk that describes the rest: names, block lists, free space, folders. |
| Foreign key | a column holding another table’s primary key: the relational way to point, by shared value. |
| Graph database | a database where relationships are first-class, built for questions that hop connections many levels deep. |
| Index | a maintained side structure (usually a B-tree) that makes chosen reads fast at the cost of every write. |
| Inode | Unix’s per-file record: where the bytes live, plus metadata; the name lives separately, in directories. |
| Join | combining rows from two tables by matching values, typically a foreign key to a primary key. |
| Key-value store | the simplest database: hand it a key, get back an opaque value; no other questions answerable. |
| NoSQL | a 2009-era banner over several non-relational families, each trading one guarantee for one superpower. |
| Object storage | the file reborn as a web service (S3 and kin): named bags of bytes over HTTP, extreme durability; where blobs belong. |
| OLTP / OLAP | the till versus the back office: many tiny urgent transactions, versus few huge analytical scans. |
| Optimizer | the database’s internal navigator: enumerates routes for your query, estimates costs, picks the cheapest. |
| Partition (network) | a failure that splits a distributed system into groups that cannot communicate; the CAP theorem’s trigger. |
| Primary key | the column(s) whose value uniquely identifies each row in a table. |
| Relational model | Codd’s 1970 idea: all data as tables of rows, related by shared values, queried declaratively. |
| Replication (and lag) | keeping live copies of data on several machines by shipping the journal; lag is how far a copy runs behind. |
| Schema / schema-on-read | the declared structure of data; schema-on-read defers that declaration to every program that reads, in code. |
| Shard | one horizontal piece of a dataset, placed on its own machine; cheap within, expensive across. |
| SQL | the standardized declarative language of relational databases: the database’s API, compositional like a grammar. |
| Transaction | a group of operations executed under the ACID promises: a promise kept across a power cut. |
| Vector embedding | a list of numbers representing an item’s meaning, enabling similarity search (“find things like this”). |
| Wide-column store | a colossal pre-sharded sorted table (Bigtable, Cassandra) built for torrential writes and known, key-shaped queries. |
| Write-ahead log | the accountant’s journal inside a database: append the change first, confirm, apply later; the mechanism behind durability and replication. |
BACK MATTER
Further Reading
Where to go when this book has done its job.
Everything below is either freely available or worth the price several times over. The order is a suggested reading path, not a ranking.
- Martin Kleppmann, Designing Data-Intensive Applications (2017). The natural next book: everything in Pieces Four and Five, at professional engineering depth, with the same honesty about trade-offs.
- E. F. Codd, “A Relational Model of Data for Large Shared Data Banks” (1970). The paper that moved the boundary. Short, readable, and startling in how much of the modern world is already inside it.
- Charles Bachman, “The Programmer as Navigator” (1973 Turing Award lecture). The road not taken, argued by its best mind; reading it makes Codd’s victory feel earned rather than inevitable.
- Donald Chamberlin and Raymond Boyce, “SEQUEL: A Structured English Query Language” (1974). SQL’s birth certificate, including the design goal of being writable by non-programmers.
- Patricia Selinger et al., “Access Path Selection in a Relational Database Management System” (1979). The optimizer blueprint: how the database hired the navigator.
- Eric Brewer, “CAP Twelve Years Later: How the ‘Rules’ Have Changed” (2012). The theorem’s author correcting its folklore, in plain language.
- Dan McKinley, “Choose Boring Technology” (essay, 2015). The default doctrine’s spiritual ancestor: innovation tokens, and why to spend them above the data layer.
- Oz Nova, “You Are Not Google” (essay, 2017). The definitive vaccination against planet-scale cosplay.
- Richard Feynman, Six Easy Pieces (1994). The method this book borrowed: respect for the reader, derivation over recitation, and the conviction that the simplest honest explanation is the deepest one.
Where Data Lives · produced June 2026. Errors of fact are the authors’; errors of judgment are teaching opportunities, and we would like to hear about both.