We use analytics cookies.We use cookies to analyze site traffic and improve your experience.
Loading...
System Design Masterclass · Devops Cicd
Free preview: the first 2 parts of this 7-part lesson.
Already bought the course? Sign in to read the whole lesson.
this lesson is part of
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design courseread the rest of this lesson in
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design coursein Devops Cicd
This lesson is part of the full System Design Masterclass. Unlock it along with 769 other lessons for a one-time payment.
One-time payment by card or PayPal
Get Lifetime AccessOne-time payment: UPI, card or netbanking
Get Lifetime Access18 Foundation lessons are free, no payment needed. Try them now
It is easy and good
“It is really nice and good Please join the course”
A team ran ALTER TABLE users ADD COLUMN phone VARCHAR(20) on a table with 50 million rows. In MySQL 5.x, this locked the entire table. For 4 hours, no reads or writes could happen on the users table. The application queued requests until timeouts, crashed, and took the entire platform down.
Schema evolution is the practice of changing database schemas safely in production. Without locks, without downtime, and without breaking applications that are still running against the old schema. It requires understanding how your database handles schema changes internally, and planning migrations that are compatible with zero-downtime deployments.
This is one of the most common sources of production outages at growing companies. The team that was fine running ALTER TABLE on a 10,000-row table is suddenly surprised when the same command locks a 50-million-row table for hours.
| Change | Safe Approach | Dangerous Approach | Why Dangerous |
|---|---|---|---|
| Add column | Add as nullable with default | Add as NOT NULL without default | Locks table to backfill in MySQL; blocks inserts |
| Remove column | Stop reading it, deploy, then drop later | Drop while app still reads it | Old app version crashes on SELECT |
| Rename column | Add new column, backfill, migrate reads, drop old | ALTER RENAME | Old app version crashes on SELECT with old name |
| Change type | Add new column with new type, migrate data | ALTER TYPE | Locks table for type cast; old app gets cast errors |
| Add index | CREATE INDEX CONCURRENTLY (Postgres) | CREATE INDEX | Locks table for the entire index build |
| Add foreign key | Add constraint as NOT VALID, then VALIDATE separately | ADD CONSTRAINT directly | Locks both tables while scanning all rows |
The expand-and-contract pattern in detail:
| Phase | Application | Database | Reversible? |
|---|---|---|---|
| Expand | v1 reads old column, ignores new | Add new column alongside old | Yes, drop new column |
| Dual-write | v2 writes to both columns, reads old | Both exist | Yes, stop writing new |
| Backfill | v2 still running | Job copies data from old to new | Yes, truncate new |
| Read switch | v3 reads new column, writes both | Both exist | Yes, switch reads back |
| Contract | v4 reads and writes only new | Drop old column | No (one-way door) |
Each phase is a separate deployment. The gap between phases can be hours or days. No single step is irreversible until the final contract phase.