In this chapter
We step back from GreenMart's own database and set it next to two very different real-world designs — a big e-commerce platform's pre-computed OLAP reporting, and a bank's immutable, append-only ledger — checking, honestly, exactly what each one buys, and what it doesn't.
The Problem in Real Life
What started as an offhand comment from Mike — that rival across town quietly asking about being bought out — has turned into something real. The acquisition is close now. One evening, Sarah starts reading about how the biggest systems in the world are actually built — a huge online store, a bank. She expects to find the same ideas GreenMart already uses, just bigger. Instead, she finds two completely different ways of thinking, and neither one looks much like what GreenMart has built.
"Wait," Mike says, reading over her shoulder. "I thought there was just one right way to build a database. Why does a bank do it so differently from a store?"
I thought there was one right way to build a database. Why does a bank do it so differently?
Mike
One Way of Thinking vs. Three, Side by Side
Three different jobs, not one right answer
Fast everyday changes, fast repeated reports, and an unerasable history are three genuinely different goals.
OLAP trades freshness for speed
A pre-computed table answers instantly, but it's only as current as the last time someone rebuilt it.
A ledger never throws anything away
Every change becomes a brand new row. The current state is always worked out from the full history, never stored as one number that can be overwritten.
A ledger isn't a replacement for Act 4's tools
Immutability guarantees history is never lost — it doesn't, by itself, stop two overlapping actions from breaking a business rule together.
Three Ways of Thinking, Three Different Jobs
Think about what GreenMart's database actually does, all day, every day: one order comes in, one sale gets recorded, one customer looks up their balance. Lots of small jobs, one at a time, each finished fast. This style has a name: OLTP, short for Online Transaction Processing. Every database GreenMart has built so far, since Act 1, has been an OLTP database. It's the right choice for exactly what a store needs.
Now think about a very different question: "What were our best-selling products last quarter, across every city?" This isn't one small job. It's one huge job — digging through months of history all at once. A system built to answer questions like this is called OLAP, short for Online Analytical Processing. To make this kind of question fast, OLAP systems often break a rule GreenMart has followed the whole course: they store the same numbers in more than one place on purpose, trading a clean design for speed. A real OLAP system usually lives in something called a data warehouse — a separate database built just for big reports like this, kept apart from the day-to-day store.
There's a third way of thinking too, and it's not about speed at all. It's how banks build their systems. A bank cares about one thing above all else: never letting a single fact disappear. Every rupee that ever moved has to stay provable, forever, even years later.
| OLTP (GreenMart) | OLAP (a big e-commerce platform) | Immutable Ledger (a bank) | |
|---|---|---|---|
| Built to be great at | Many small, fast changes | Huge reports over lots of history | Never losing a single fact |
| How data is shaped | Clean, separate, no repeats | Pre-computed, often repeated on purpose | One row per event, nothing ever changed |
| What you give up | Slow at huge reports | Answers can be a little out of date | More rows to store, more to add up each time |
| A GreenMart example | Recording today's sale | A best-sellers report for last quarter | A full, provable history of a customer's balance |
None of these three is simply the 'best' one. Each is the right tool for a different job — and a single large company can genuinely use all three at once, for different parts of the same business.
This is the exact shape of almost every report GreenMart has written since Act 3: clean, separate tables, joined together whenever someone asks a question. It gives the right answer every time. But look closely at what it actually does — every single time someone runs this report, SQLite has to redo the same join and the same grouping work again, from nothing, even if the last person asked the exact same question five minutes ago.
SELECT p.Name, SUM(oi.Quantity) AS UnitsSold, SUM(oi.Quantity * p.Price) AS RevenueFROM OrderItems oiJOIN Products p ON p.ProductID = oi.ProductIDJOIN Orders o ON o.OrderID = oi.OrderIDGROUP BY p.NameORDER BY Revenue DESC;
EXPLAIN QUERY PLAN shows the real cost hiding behind this simple-looking query: one scan, two searches, and two separate sorting steps.
A system built for heavy reporting — the kind a massive e-commerce platform runs nonstop, all day — usually doesn't wait for someone to ask a question before doing the work. Instead, it computes the answer once, on a schedule, and saves it into its own table. In a real data warehouse, a table like this is called a fact table, and this whole style of building several ready-made tables for reporting is often called a star schema. It's the same CREATE TABLE ... AS SELECT trick from Act 3's materialized-view chapter — just used as a real, deliberate design choice this time, not a one-off shortcut.
CREATE TABLE ProductSalesSummary ASSELECT p.Name, SUM(oi.Quantity) AS UnitsSold, SUM(oi.Quantity * p.Price) AS RevenueFROM OrderItems oiJOIN Products p ON p.ProductID = oi.ProductIDJOIN Orders o ON o.OrderID = oi.OrderIDGROUP BY p.Name;
ProductSalesSummary now holds the finished answer, sitting there, ready to be read directly.
Same question. Same answer. But now there's only one table, and nothing left to join.
SELECT * FROM ProductSalesSummary ORDER BY Revenue DESC;
EXPLAIN QUERY PLAN drops from a scan plus two searches plus two sorting steps, down to just one scan and one sorting step. The cost of this speed: ProductSalesSummary is only as fresh as the last time someone rebuilt it — unlike the live join, which always reflects right now.
This is how GreenMart has tracked money since Act 1: one column, changed directly whenever it needs to update. It's simple, and for a small store, that simplicity is genuinely fine.
UPDATE Customers SET BalanceDue = BalanceDue - 40 WHERE CustomerID = 101;SELECT * FROM Customers WHERE CustomerID = 101;
The instant this UPDATE runs, the fact that BalanceDue was ever 140 is gone. Nowhere in the database does it say that number used to be anything else.
A real bank almost never stores a balance as one number that gets changed. Instead, every single movement of money — every deposit, every payment, every charge — becomes its own permanent row that never gets touched again. The balance itself isn't stored anywhere. It's worked out fresh, every time, by adding up every row that ever happened. This style has a name in the software world too: event sourcing, or simply an append-only ledger.
CREATE TABLE AccountLedger (EntryID INTEGER PRIMARY KEY,CustomerID INTEGER NOT NULL REFERENCES Customers(CustomerID),Amount NUMERIC NOT NULL,EntryDate DATE NOT NULL,Description TEXT NOT NULL);INSERT INTO AccountLedger (EntryID, CustomerID, Amount, EntryDate, Description) VALUES(1, 101, 140, '2026-07-01', 'Opening balance'),(2, 101, -40, '2026-08-20', 'Payment received');SELECT CustomerID, SUM(Amount) AS CurrentBalance FROM AccountLedgerWHERE CustomerID = 101GROUP BY CustomerID;
CurrentBalance comes back as 100 — the exact same number GreenMart's UPDATE gave. But here, every single step that led to that number is still sitting right there in the table, forever.
Suppose someone made a mistake — say, the same payment got typed in twice by accident. In a ledger, nobody goes back and deletes the wrong row, or quietly edits it like it never happened. Instead, someone adds a brand new row that cancels the mistake out. The wrong entry stays visible forever, right next to the entry that fixes it.
INSERT INTO AccountLedger (EntryID, CustomerID, Amount, EntryDate, Description) VALUES(3, 101, -40, '2026-08-21', 'Correction: payment recorded twice by mistake'),(4, 101, 40, '2026-08-21', 'Reversal of duplicate payment entry');SELECT CustomerID, SUM(Amount) AS CurrentBalance FROM AccountLedgerWHERE CustomerID = 101GROUP BY CustomerID;
CurrentBalance is still exactly 100 — correct. And now the ledger honestly shows that a mistake happened and was caught, instead of pretending it never did.
Here's something GreenMart's own mutable BalanceDue column can never do: answer what the balance used to be on some earlier date. A mutable column only ever holds one value — right now. The moment it changes, whatever it held before is gone for good. A ledger never loses that — asking "what was true on August 20th" is just a matter of adding up only the rows that existed by then.
INSERT INTO AccountLedger (EntryID, CustomerID, Amount, EntryDate, Description) VALUES(5, 101, 200, '2026-08-25', 'New order placed on credit');SELECT SUM(Amount) AS BalanceOnAug20 FROM AccountLedgerWHERE CustomerID = 101 AND EntryDate <= '2026-08-20';SELECT SUM(Amount) AS BalanceToday FROM AccountLedgerWHERE CustomerID = 101;
BalanceOnAug20 comes back as 100 — exactly what the balance really was on that date. BalanceToday comes back as 300, after one more real charge landed on the 25th. Both answers sit in the exact same table, at the exact same time, because nothing was ever thrown away.
So which one is right? All three are — just for different jobs. GreenMart's OLTP design is right for the fast, everyday work of running a store. An OLAP-style pre-computed table is right when the exact same expensive report gets asked over and over. A bank's ledger is right when proving exactly what happened, and when, matters more than the convenience of one simple number.
One thing is worth saying clearly, though, so nothing here gets overclaimed: an immutable ledger does not, by itself, stop the exact race condition from Act 4's flash sale. Two withdrawals could still land at almost the same moment and jointly push an account below zero — a ledger alone doesn't rule that out. Guarding against that still needs the same transactions and constraints from Act 4. What a ledger really promises is something else, and it's just as valuable: nothing that ever happened can be quietly erased, overwritten, or denied later.
Key Takeaway
OLTP, OLAP, and an immutable ledger aren't three ways of solving the same problem — they're honest answers to three different questions: fast everyday changes, fast repeated reporting, and a record of everything that can never be erased.
Why This Matters
Knowing which of these three jobs a real system is actually trying to do — before reaching for a design — is exactly the skill that separates someone who's only memorized SQL syntax from someone who can genuinely design a database for the problem sitting in front of them.
GreenMart finally has words for something it's been circling since Act 1: every choice this whole course made was really an OLTP choice, and it was the right one every time. If GreenMart ever needed heavy reporting or an unbreakable money trail, it now knows exactly which philosophy to reach for, and why.
