Tables and schema

DataTier 1 · hear it this weekPhase 2 · Make it a store

The designed structure of a database: which tables exist, what columns they have, and how they relate. Changing it is real work.

Once data lives in a database it needs a defined shape, or every record could carry different fields and nothing could be relied on. Code that reads a customer should know a customer always has an id, a name, and an email. Tables and schema exist to fix that structure up front, so data stays consistent and queries can trust what they will find.

The schema is the blueprint. A products table, an orders table, a customers table, each with defined columns. An order row points to which customer placed it and which products it contains. These relationships are designed deliberately.

Because code and data depend on the shape, changing it (adding a column, splitting a table) is a schema change, or migration, done carefully so nothing breaks.

A junior PM, stuck

I asked engineering to add loyalty points to customer profiles, thinking it was one number on a screen. They came back with "that is a schema change and a migration on the customers table" and a multi-day estimate. I could not push back or agree, because I genuinely cannot picture why storing one extra number per customer is big work.

Loyalty points are one column, you are right about that. The size is not the column, it is that a schema is a fixed shape every row and every query already depends on, so changing the shape means touching every existing row and re-checking everything that reads it. Below are the three real tables and the exact migration line, so you can see the one column turn into work spread across the whole table.

Three linked tables and the migration that adds one column
customers and products: two tables the schema defines
customers
id | tier
u_88231 | regular
products
id | name | price
p_1042 | Kacchi Biryani (Family Pack) | 649
orders: the table that links the other two
id | customer | product | amount | status
o_5512 | u_88231 | p_1042 | 649 | shipped
The migration: add loyalty_points to customers
ALTER TABLE customers ADD COLUMN loyalty_points integer NOT NULL DEFAULT 0;
ALTER TABLE
SELECT id, tier, loyalty_points FROM customers;
u_88231 | regular | 0
... | ... | 0
(every existing row now carries the new column)

Click a step to see the lines it points at.

Scoping a new stored field as a screen change. Adding loyalty_points is not a label, it is a column every existing customer row and every reader of that table has to absorb; that is why engineering calls it a migration.
Confusing displaying data with storing data. Showing a number you already have is small work; capturing a brand new fact means changing the schema, which is a different order of effort.
Ignoring the relationships between tables. An order points at a customer and a product by id; a change that breaks those links breaks far more than the one table you were thinking about, so ask what else references it.
Deciding the schema late. The cheapest time to ask "will we ever need points, tiers, referral source" is during planning; bolting each one on afterward is a separate migration every time.
Hearing "migration" as stalling. A migration on a large table is genuine, careful work, often run off-peak to avoid locking rows during traffic; treat the estimate as the real cost, not a negotiation.

Reply to engineering: "Understood, adding loyalty_points is a column plus a migration that backfills every customers row and touches everything reading that table, not a screen change. What is the safe window to run it." You read three linked tables and saw one column become table-wide work, which is the skill.

"That's a schema change" is engineering saying the request touches the foundation, so it is bigger than it looks.
Good schema design early prevents painful migrations later; PMs who understand this ask about future needs during planning.

"Adding loyalty points means a schema change and a migration on the customers table."

Appears in Phase 2, Make it a store.