advanced · 23 minute study
Change a schema while old data still exists
A new schema is easy to describe on an empty database. A deployable migration must also explain what happens to retained rows and older application versions.
Useful preparation · 2 prerequisites
Use this as a map, not a lock. If these ideas are familiar, continue.
- Make impossible relationships unrepresentable — A form can look correct while an import or competing request writes a broken relationship. Integrity belongs at the data boundary every writer shares.
- Make a change an all-or-nothing unit — An order without its lines is not half a successful feature. It is a broken state that later screens, reports and retries must somehow interpret.
First, build a mental model
A migration is a controlled transition between supported states. Expand what the database accepts, move data and consumers, then contract only after compatibility is proven.
- Adding a nullable column can preserve old records while new code begins writing it. A future NOT NULL requirement needs an explicit valid-data transition.
- A unique index on company plus external reference can enforce uniqueness within each company. The partial predicate here intentionally ignores missing references.
- Check real duplicate/null distributions before tightening constraints. Never invent a harmless-looking default that changes the meaning of historical records.
- Review forward migrations and replay/upgrade paths. SQLite can run this example, but PostgreSQL locking, concurrent index options and ALTER details require separate validation.
ALTER TABLE orders ADD COLUMN external_ref TEXT;
CREATE UNIQUE INDEX orders_company_reference
ON orders(company_id, external_ref)
WHERE external_ref IS NOT NULL;
UPDATE orders SET external_ref = 'web-101' WHERE id = 101;
SELECT id, company_id, external_ref FROM orders ORDER BY id;- Expand
Old rows gain a nullable column without fabricating reference IDs.
- Constrain known values
A repeated non-null reference within one company conflicts; missing references remain allowed.
- Move consumers
New code can write references while migration/backfill work explicitly handles retained rows.
Production thinking
Take this beyond the example.
Preserve applied migration history. Validate both a clean replay and upgrade from supported existing state. Record schema/code ordering and a forward-recovery strategy; do not assume data loss is reversible.
Sources and further reading
Your evidence
unseen is a local learning signal, not a credential or proof of production competence.
Explain the mental model, then explicitly acknowledge it. Opening a page is not evidence.
Supported retries can complete this lesson. Independent evidence and delayed review determine the skill stage.
Next lesson · Reconcile claims against evidence →