data-infra
Glossary ↗Database Migration
A database migration is a single, version-controlled file describing an incremental change to a database's schema — creating a table, adding a column, adding an index — designed to be applied in a fixed order across every environment (a developer's laptop, staging, production) so the schema stays identical and reproducible everywhere, rather than someone manually running `ALTER TABLE` commands by hand and hoping every environment stays in sync. Why it matters for AI/SaaS builders: migrations are the mechanism by which a schema evolves safely alongside a growing product — adding the `embedding vector(1536)` column for a new RAG feature, adding a `tenant_id` column to enforce multi-tenant isolation, or adding an index to fix a slow query are all migrations, checked into version control alongside the application code that depends on them, so a `git checkout` of any historical commit corresponds to a schema a migration tool can reproduce exactly. How it works: migration tools (Laravel's built-in migrations, Prisma Migrate, Alembic for Python, Rails migrations) track which migrations have already run (typically in a dedicated `migrations` table in the database itself) and apply only the new ones in order when `migrate` is run. Migrations are written to be reversible where practical (an `up` step and a `down` step) so a bad deploy can be rolled back cleanly. The genuinely hard part in production systems isn't writing migrations — it's running them safely against a live, high-traffic database without downtime: adding a column is usually safe and fast, but adding a `NOT NULL` constraint to an existing large table, or building an index, can lock the table and block writes for the duration unless done carefully (e.g., Postgres's `CREATE INDEX CONCURRENTLY`, which builds an index without holding a table-wide lock, at the cost of taking longer and being non-transactional). Worked example: a team adding vector search to their SaaS writes a migration `AddEmbeddingToDocuments` that runs `ALTER TABLE documents ADD COLUMN embedding vector(1536);` followed by `CREATE INDEX CONCURRENTLY ON documents USING hnsw (embedding vector_cosine_ops);` — the concurrent index build lets the production database keep serving live reads and writes throughout the multi-minute index build on a 5-million-row table, instead of the blocking, non-concurrent version locking writes to the table until it finishes. The migration is peer-reviewed before merge specifically because of this production-safety concern — a reviewer familiar with the team's traffic patterns catches that the naive `CREATE INDEX` (without `CONCURRENTLY`) would have taken the documents table offline for writes during business hours, the kind of mistake that's invisible in a local dev environment with a few hundred rows and only becomes obvious at production scale.
Related terms