transactions, or overselling
Stonebraker likes a small example. A department has employees. You fire the last one. Now what? Do you delete the department, or do you leave a department with nobody in it — a ghost that every later query has to step around? There is no right answer in the abstract. There is only your answer, and the question is where you write it down.
You can write it in hope: a comment in the codebase, a convention everyone is supposed to follow, a cleanup script someone runs on Fridays. Or you write it in the database, as a constraint, where it cannot be forgotten and cannot be skipped by the one code path that didn't get the memo. Referential integrity is just that decision, encoded once, enforced on every write.
-- the rule lives in the schema, not in a Friday cleanup script
CREATE TABLE department (
id int PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE employee (
id int PRIMARY KEY,
dept int NOT NULL REFERENCES department(id) ON DELETE RESTRICT
);
-- ON DELETE RESTRICT: you cannot drop a department that still has staff.
-- swap for ON DELETE CASCADE if your answer is "delete the department too."
-- either way the answer is in one place, and the database keeps it.
For a stretch Google preached eventual consistency as the way to do concurrency control at scale. Don't coordinate on every write; let each site act locally and reconcile later. Walk the warehouse. You stock widgets. There's a site on the east coast and a site on the west coast.
One widget is left. East coast sells it: decrement the local count, send an async message west, "eventually" the two coasts agree. West coast sells the same last widget at the same moment: decrement locally, send its own async message east. Both sales succeeded. Both messages arrive. Now the counts merge.
The integrity constraint you wanted — stock > -1 — is exactly the thing eventual consistency cannot hold. It can only notice the violation after it has already shipped a widget that does not exist. There is no widget. Somebody is getting a refund and an apology.
This is not a contrarian take that lost. Google figured it out. Jeff Dean and the team that had pushed eventual consistency hardest reversed course; Spanner went back to a conventional transactional system — real distributed transactions, real consistency, the boring guarantees a relational database always offered.
When the company with the most servers on earth, the one that invented the eventual-consistency pitch, walks all the way back to transactions, the question stops being "can I afford correctness?" The default is correctness. You do the work to leave it, and you'd better have a reason.
There is a reason, and it's worth naming because it's narrow. You may oversell when the business can absorb it. Amazon "usually ships in 24 hours" — if the warehouse comes up one short, they buy more, or they wait a day, and the customer was promised "usually" anyway. The slack is in the business model, not the database.
stock > -1 never fails because it can't.Most enterprises cannot make that promise. So correctness is the default and eventual consistency is the exception you reach for in a specific business that can carry the cost — not a knob you turn because a benchmark looked slow.
This is about to matter more, not less. Read-only AI hides the problem: ask a model a question, it answers, nothing changes. Read-write AI brings it all back. Move $100 between two accounts with two agents — one debits, one credits. That is a distributed transaction again. It has to be atomic.
-- one transaction, both legs, all-or-nothing
BEGIN;
UPDATE account SET balance = balance - 100 WHERE id = 'A';
UPDATE account SET balance = balance + 100 WHERE id = 'B';
COMMIT;
-- if anything between BEGIN and COMMIT fails, both updates vanish.
-- the $100 is never half-moved. it all happens, or it never happened.
Correctness-by-default removes a whole class of bug you would otherwise debug in production at 3am: the half-moved dollar, the negative stock, the order that references a customer who was deleted. What it removes: the reconciliation job, the apology email, the spreadsheet someone keeps to catch the cases the system let through.
This is the data-tier throughline again. Remove to accelerate. Fewer datastores, fewer failure modes — and within the one you keep, fewer guarantees you've quietly weakened. Part 2 said the engine grows to fit the problem. This part says the engine stays honest while it does. The transaction is not the slow path you optimize away. It is the thing that lets you sleep.
← Part 2: The Extensible Core · Mostly Postgres · Part 4: The Sprawl Tax →