Storing data: tables, keys, SQL, documents and the three kinds of storage
Servers forget; databases remember. Almost every design question ends up being about data: how it's shaped, how it's found again, and what happens when two people change it at once or a machine crashes mid-write. This module covers the basics you need before the data modules (11 to 17): tables and keys, enough SQL to read a query, other data shapes, transactions, how data is turned into bytes, and the difference between block, file and object storage.
1. The idea
Why not just write files? You can, and for logs and images that's exactly what we do. But for records that many users read and change at once, a database gives you four things files don't: safe concurrent changes, crash safety (a half-finished write is undone), queries ("all orders over $50 this week") and indexes to answer them fast.
| Term | What it means | Example |
|---|---|---|
| Table, row, column | A table holds one kind of thing; each row is one of them; each column is one attribute. | A users table, one row per user, a city column |
| Schema | The declared shape: tables, columns and their types. | amount is a decimal, created_at a timestamp |
| Primary key | A column whose value is unique per row and identifies it. | users.id = 42 |
| Foreign key | A column that refers to another table's primary key. | orders.user_id = 42 |
| Index | An extra sorted structure that finds rows by a column without scanning the table. | An index on users.email for logins |
| SQL | The standard language for asking relational databases questions. | SELECT name FROM users WHERE city = 'Paris' |
| Transaction | A group of changes that all happen or none do (ACID: atomic, consistent, isolated, durable). | Moving money between two accounts |
| Key-value store | Stores a value under a key; you can only look it up by that key. | Redis, DynamoDB |
| Document store | Stores self-contained documents (usually JSON-like), nested data and all. | MongoDB |
| Serialization | Turning data in memory into bytes to store or send, and back. | JSON (text) or Protobuf (binary) |
SQL in six statements
CREATE TABLE users (id BIGINT PRIMARY KEY, name TEXT, city TEXT);
CREATE TABLE orders (id BIGINT PRIMARY KEY, user_id BIGINT REFERENCES users(id),
amount NUMERIC(10,2), status TEXT);
INSERT INTO users (id, name, city) VALUES (1, 'Ada', 'London');
SELECT name, city FROM users WHERE city = 'London';
UPDATE orders SET status = 'shipped' WHERE id = 3;
DELETE FROM orders WHERE status = 'cancelled';
SELECT u.name, o.amount -- a join: combine two tables
FROM orders o JOIN users u ON u.id = o.user_id;
2. How it works
The same order, stored three ways
How you shape data decides which questions are cheap. Press Play to see one customer and their orders as relational tables, a document and key-value pairs.
All or nothing: a transaction
Moving $50 from Ana to Ben is two writes. If the server crashes between them, money vanishes, unless both writes are one transaction.
Block, file and object storage
Below every database and file there's storage of one of three kinds, and they offer very different operations.
| Kind | What you get | Typical use | Examples |
|---|---|---|---|
| Block | A raw disk for one server; it puts a file system on top. Fast, byte-level updates. | A database's own data files | Local SSDs, cloud volumes (Amazon EBS) |
| File | Folders and files shared over the network by many servers. | Shared content, legacy apps | NFS, Amazon EFS |
| Object | Whole objects stored and fetched by key over HTTP. Huge, cheap, durable; no in-place edits. | Photos, videos, backups, data lakes | Amazon S3, Google Cloud Storage, Azure Blob |
3. Try it yourself
Run some SQL
A tiny shop database with two tables. Pick a query to see what it returns and how it works.
Text vs binary: what one record costs
The same user record encoded as JSON and as Protobuf (a binary format). Change the values and watch the bytes. Protobuf's numbers are exact: it's the real encoding.
Protobuf schema used: message User { int64 id = 1; string name = 2; string city = 3; int32 age = 4; bool verified = 5; }, with city "London" and verified true.
4. Trade-offs
Relational vs other shapes
Tables with keys answer almost any question with joins and keep each fact in one place; they're the right default. Documents fit data that's always read whole; key-value stores fit lookups by one key at huge scale. Module 13 compares them all.
Store each fact once vs copy for speed
Normalising (each fact once, linked by keys) keeps data consistent; denormalising (copying a user's name into every order) makes reads faster and updates riskier. Start normalised; copy on purpose.
JSON vs binary formats
JSON is readable, self-describing and universal, but larger and slower to parse. Protobuf and Avro are compact and fast, and need a schema to read. Public APIs usually use JSON; internal services and logs often use binary.
Database vs object storage for files
Databases are fast for small records and expensive per gigabyte; object storage is cheap and huge but slow to start each request. Keep files in object storage and their metadata (owner, size, key) in the database.
5. In real systems
Most products keep their core data in a relational database (PostgreSQL or MySQL, often managed by a cloud provider), add Redis as a cache, put files in object storage, and add specialised stores (search, analytics) only when a need appears. The data modules go deeper:
| Topic | Module |
|---|---|
| Designing tables, keys and relationships | 11 Relational data and modeling |
| How indexes and storage engines work | 12 Indexes and storage engines |
| Key-value, document, wide-column, search and more | 13 Choosing a database |
| Two people changing the same row | 17 Transactions and contention |
| Photos, videos and files | 10 Blob storage and CDNs |
Say it in the interview
- "Primary vs foreign key?" A primary key uniquely identifies a row in its table; a foreign key in another table points at it. Together they model relationships like "an order belongs to a user".
- "What's a transaction for?" To make several changes all-or-nothing and isolated from other users' changes, so a crash or a race can't leave data half-updated.
- "Where do user-uploaded photos go?" In object storage, served through a CDN; the database stores only the photo's key and metadata.
- Large files stored inside database rows.
- Money stored as floating-point numbers.
- A design with no stated primary key or with every query scanning the whole table.
6. Remember it
How this hook works: what the three rules mean
What the slogan means, phrase by phrase
- "Every row a key"
- A primary key makes each record findable and referable.
- "every fact once"
- Store each fact in one place and link to it, so it can't disagree with itself.
- "every change all-or-nothing"
- Group related writes in a transaction, so crashes and races can't leave half a change.
Why this picture fits: the three most common data bugs are unfindable rows, contradictory copies, and half-applied changes; each rule prevents one.
The story → the concept
| Library | Database |
|---|---|
| Book number | Primary key |
| Loan slip referring to book and member | Foreign keys |
| Catalogue | Index |
| Marking out the book and filing the slip together | Transaction |
7. Common mistakes
8. Design exercise (25 minutes)
- Model a blog (10 min). Tables for users, posts, comments and likes, with primary and foreign keys. Which columns need an index?
- Write the queries (10 min). A post with its comments and authors; the ten most-liked posts this week; all comments by one user.
- Find the transaction (5 min). Which action in the blog needs several writes to happen together?
9. Self-check quiz
orders.user_id refers to users.id. What is orders.user_id?
A transaction debits one account and crashes before crediting the other. What's stored afterwards?
Where should a 40 MB video go?
Protobuf is smaller than JSON. What's the catch?
Logins look users up by email in a table of 50 million rows. What makes that fast?
10. Go deeper
| Resource | Time | Why |
|---|---|---|
| SQLBolt | 1–2 h | Interactive SQL lessons from zero. |
| The PostgreSQL tutorial | 1 h | Tables, queries, joins and transactions in a real database. |
| Protobuf encoding | 20 min | Exactly how the bytes in the lab are produced. |
| Block vs file vs object storage (AWS) | 10 min | The three kinds of storage compared. |