On a new branch (
feat/safe-migrations) with a copy of your DB. Do not look at solutions.md before submitting.
Exercise 1 — The rename without downtime
Model: your event has title (if it's already called that, create a temporary twin field for the exercise).
- Add
label = CharField(null=True)(EXPAND) and migrate. - Write the data migration copying
title → labelin batches (paginated bypk), with a noop reverse. - Change the code to write/read
label(dual write: save to both). Demonstrate in the shell that both columns stay equal after creating 3 events. - Simulate the SWITCH (the code now only uses label) and write the CONTRACT migration dropping
title. What would running the old code right after this step break?
Exercise 2 — The dangerous NOT NULL, done safely
- Try
AddField(field=CharField(max_length=16, null=False, default=""))on a table with rows: what does Django generate and what does PostgreSQL do? - Do it the long way: add nullable → backfill with RunPython in batches →
AlterFieldto NOT NULL. Verify each step's time mentally (or\timingon the SQL steps). - Install
django-migration-linterand run the lint on your app: does it flag dangerous operations in your history?
Exercise 3 — CONCURRENTLY index
- In a migration with
atomic = False, useRunSQLto create a CONCURRENTLY index on a queried column (e.g.reservation.created_at). - Try the same without CONCURRENTLY on a big table (or simulate with 100k rows): does it block writes while running? What happens if the CONCURRENTLY fails halfway (an INVALID index)?
- Write the check to detect INVALID indexes:
SELECT * FROM pg_index WHERE NOT indisvalid;
Exercise 4 — Lesson 08's three improvements
Apply your noted improvements with safe migrations (one per improvement, green lint):
- NOT NULL with backfill where appropriate.
- Coherence CHECK (
expires_at > created_aton reservation) — what happens to old rows violating it? (backfill/fix first). - Unique
slugon event with generation for the historical rows.
Submit
Paste migrations and outputs. Lesson 11 closes; next Lesson 12 — NoSQL.