← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Database Migrations

General PHP 5.0+ Intermediate
debt(d7/e5/b7/t5)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The tools listed (phinx, doctrine-migrations, laravel-migrations) manage migrations but don't automatically detect when someone bypasses them with direct ALTER TABLE statements. Detection requires manual code review or process audits to ensure all schema changes go through migration files. The detection_hints explicitly state automated detection is 'no'.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix says 'every schema change must be a reversible migration file' — retroactively creating migrations for manual changes requires examining production schema, creating migration files, potentially writing down() methods, and testing rollback paths. For accumulated manual changes, this spans multiple migration files and database state reconciliation.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). Database migrations apply across all contexts (web, cli) and fundamentally shape how teams deploy and coordinate. Once a project establishes a migration workflow (or lacks one), every future schema change and every developer is affected. The choice of migration tool and conventions becomes load-bearing infrastructure that every database-touching feature must respect.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5). The misconception field explicitly states developers wrongly believe 'migrations are only needed for schema changes' when they should also cover data transformations, seed corrections, and index changes. This is a documented gotcha that most developers eventually learn, but the initial mental model of 'migrations = CREATE/ALTER TABLE only' leads to inconsistent database states across environments.

About DEBT scoring →

Also Known As

DB migrations schema migrations migration files

TL;DR

Version-controlled, incremental scripts that evolve the database schema alongside code, enabling reproducible deployments and rollbacks.

Explanation

Database migrations track schema changes as numbered, ordered scripts checked into version control alongside application code. Each migration has an up (apply) and down (rollback) operation. Migration tools for PHP include Doctrine Migrations, Phinx, and Laravel Migrations. Migrations must be backward compatible during blue/green or canary deployments — the old code must work with the new schema until deployment completes. Best practices: one change per migration, never modify a committed migration (add a new one), include data migrations where schema changes require data backfill, and run migrations atomically in a transaction where the database supports it.

Common Misconception

Database migrations are only needed for schema changes. Migrations should also cover data transformations, seed data corrections, and index changes — anything that modifies the database state should be versioned and reproducible across all environments.

Why It Matters

Database migrations version-control schema changes alongside code — every developer and environment gets the same schema evolution history, and rollbacks are explicit rather than manual.

Common Mistakes

  • Running ALTER TABLE directly on production without a migration — the change is not reproducible.
  • Migrations that lock the table on large datasets — use online schema change tools for big tables.
  • Irreversible migrations with no down() method — prevents rollback if the deploy fails.
  • Multiple developers running conflicting migrations simultaneously — use sequence numbers or timestamps.

Code Examples

✗ Vulnerable
// Schema change run directly on production — not tracked:
mysql -u root -p production_db -e "ALTER TABLE users ADD COLUMN phone VARCHAR(20)";
// Not in version control, not reproducible, team doesn't know it happened

// Migration:
public function up(): void {
    Schema::table('users', fn($t) => $t->string('phone', 20)->nullable());
}
✓ Fixed
// Phinx migration — up() and down() must be inverse operations
class AddStatusToOrders extends AbstractMigration {
    public function up(): void {
        $this->table('orders')
             ->addColumn('status', 'string', [
                 'limit'   => 20,
                 'default' => 'pending',
                 'after'   => 'total',
             ])
             ->addIndex('status')
             ->save();
    }

    public function down(): void {
        $this->table('orders')
             ->removeColumn('status')
             ->save();
    }
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 122
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping F 0 pings S 0 pings S 2 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 2 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 1 ping W 0 pings T 1 ping F 0 pings S 0 pings S 2 pings M 1 ping T 0 pings W 0 pings T 0 pings F 1 ping S
Bing 1
No pings yesterday
Amazonbot 12 Perplexity 10 Scrapy 9 PetalBot 9 Google 8 Ahrefs 8 SEMrush 8 ChatGPT 6 Unknown AI 4 Bing 4 Twitter/X 2 Brave Search 2 Applebot 2 Meta AI 1
crawler 79 crawler_json 5 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Every schema change must be a reversible migration file committed to git — never alter production tables manually
📦 Applies To
PHP 5.0+ web cli laravel symfony doctrine
🔗 Prerequisites
🔍 Detection Hints
Schema changes applied manually to production without migration files in version control
Auto-detectable: ✗ No phinx doctrine-migrations laravel-migrations
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update


✓ schema.org compliant