Database

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

Organized, permanent storage for your product's information, built to be searched and updated safely.

A running program forgets everything the moment it stops, but a product has to remember orders, accounts, and inventory across restarts and across millions of records. Keeping that in flat files becomes slow and unsafe when many requests read and write at once. A database exists to store data durably and let many callers query and change it safely and quickly.

Your 500 products, their prices, and their stock counts need one trustworthy home. A database keeps them in tables, rows and columns, and lets the backend read and change them reliably, even with many requests at once.

Change a price once, in the database, and every customer sees the new price instantly, because the page reads from there rather than having the price baked in.

A junior PM, stuck

Ops wants the Kacchi Biryani price changed from 649 to 699 for the Friday promo, and I said I would get it done. Then I realized I do not actually know where that 649 physically lives: in the app, in a file, somewhere else. I cannot tell whether I am asking a dev for a five-minute edit or a whole release.

That 649 lives in exactly one place: a cell in the products table of the store's database. Below is that table the way an engineer sees it in a SQL client, real rows, trimmed from twelve to eight so we can read every line, plus the one line that changes the price and a read that proves it changed. Five minutes with this and you can tell ops exactly what you are asking for.

The products table and the promo price change, in a SQL client
products table, before the change
id | name | category | price | in_stock
p_1042 | Kacchi Biryani (Family Pack) | Rice | 649 | true
p_1043 | Beef Tehari | Rice | 280 | true
p_1044 | Morog Polao | Rice | 320 | true
p_1045 | Chicken Roast Thali | Meals | 240 | true
p_1046 | Ilish Bhaji Thali | Fish | 360 | false
p_1047 | Daily Veg Tiffin | Veg | 150 | true
p_1048 | Khichuri with Egg | Meals | 160 | true
p_1049 | Mutton Rezala | Meals | 420 | true
The change
UPDATE products SET price = 699 WHERE id = 'p_1042';
UPDATE 1
The same row, read back
SELECT name, price FROM products WHERE id = 'p_1042';
name | price
Kacchi Biryani (Family Pack) | 699
(1 row)

Click a step to see the lines it points at.

Scoping every number change as a release. A price that lives in a table changes with one query; wrapping a two-minute data change in a full deploy cycle burns days for nothing.
Assuming every number lives in a table. Values written into code or config really do need a release, so ask which table and which column before promising ops a quick fix.
Making the ask by name instead of id. "Change the Kacchi price" leaves the engineer to find the row; "price to 699 where id is p_1042" names exactly one row and nothing else.
Never asking for the receipt. UPDATE 1 versus UPDATE 12 is the difference between one promo price and the whole menu costing 699; ask for the row count in the thread.
Checking the table and skipping the storefront. A cached menu can keep serving 649 for a few minutes after the cell says 699; confirm on the real menu screen before telling ops it is live.

Reply to ops with: "That is a one-row data change, not a release. I will ask Rafi to set price to 699 in the products table where id is p_1042 and paste back the row count." You found the cell a number lives in, read the line that changes it, and checked the receipt: that is the skill.

"Is that in the database?" and "that needs a schema change" are everyday phrases. Features that add new kinds of data are bigger than features that just display existing data.
Data you never captured cannot be reported on later. Deciding what to store is a product decision with a long tail.

"We don't store that field, so we can't build the report without a migration."

Appears in Phase 2, Make it a store.