Application architecture is not only Python modules. Unique constraints, ownership rules, triggers, indexes, and stored procedures decide which states the system can represent.
A migration is executable architecture because it changes those rules for live data.
Write the invariant first#
Instead of “add an index,” state the guarantee:
A user can have at most one daily recovery score for a local date.
Then encode it:
create unique index if not exists computed_scores_user_date_unique
on public.computed_scores (user_id, score_date);
The application may check before inserting for a friendlier error, but the database arbitrates concurrent writes.
Separate shape, data, and cutover#
A safe change often has phases:
- add a nullable column or new table;
- deploy code that can read old and new representations;
- backfill existing data in bounded batches;
- verify completeness and correctness;
- add stricter constraints;
- remove obsolete reads and columns later.
A hard cut is appropriate when all clients and deployments can change together. Compatibility is valuable only when there is a real mixed-version window.
Make reruns safe#
Use guards such as if not exists, deterministic updates, and conflict handling where they preserve the intended result. A migration that fails halfway should have a documented recovery path.
Idempotent does not mean hiding every error. A changed constraint with the same name should fail rather than pretending the desired schema exists.
Test important migration behavior#
Tests can assert that critical migrations contain the expected constraint, policy, or function definition. Stronger integration tests apply migrations to a representative database and verify behavior with conflicting writes and legacy rows.
Review data volume, lock duration, index build behavior, and rollback options. A syntactically correct statement can still create an outage on a large table.
Schema design controls correctness after application bugs, retries, and concurrent requests. Treat migrations with the same care as the services that depend on them.