Isaac.

Data Migration Strategies

Plan and execute safe database migrations in production.

By EMEPublished: February 20, 2025
databasemigrationdataschema changeproduction

A Simple Analogy

Data migration is like moving a family to a new house. Plan carefully, pack methodically, verify everything works, and keep backup of what you had—just in case.


Migration Patterns

| Pattern | Risk | Time | Use Case | |---------|------|------|----------| | Big Bang | High | Fast | Development | | Blue-Green | Low | Slow | Production | | Rolling | Medium | Medium | Large systems | | Shadow | Low | Slow | Validation |


Blue-Green Deployment

// Keep two identical databases: Blue (old) and Green (new)
// Switch traffic after validation

var activeDatabase = await GetActiveDatabaseAsync();

if (activeDatabase == "blue")
{
    // Migrate data to green
    await MigrateDataAsync("blue", "green");
    
    // Validate green
    if (await ValidateAsync("green"))
    {
        // Switch traffic to green
        await UpdateConfigAsync("activeDatabase", "green");
    }
    else
    {
        // Rollback to blue
        await UpdateConfigAsync("activeDatabase", "blue");
    }
}

Rolling Migration

// Migrate in batches to minimize downtime

public async Task MigrateInBatchesAsync(
    IEnumerable<int> userId,
    int batchSize = 1000)
{
    var batches = userId
        .Chunk(batchSize)
        .ToList();

    foreach (var batch in batches)
    {
        try
        {
            await MigrateBatchAsync(batch);
            logger.LogInformation($"Migrated batch of {batchSize}");
        }
        catch (Exception ex)
        {
            logger.LogError($"Batch failed: {ex.Message}");
            await RollbackBatchAsync(batch);
        }
    }
}

Schema Changes

-- Add column (backwards compatible)
ALTER TABLE Users ADD Email NVARCHAR(255) NULL;

-- Remove column (requires app update first)
-- Step 1: App stops using column
-- Step 2: Migrate data
ALTER TABLE Users DROP COLUMN LegacyField;

-- Rename with safe approach
-- Step 1: Add new column
ALTER TABLE Users ADD NewColumnName INT;

-- Step 2: Copy data
UPDATE Users SET NewColumnName = OldColumnName;

-- Step 3: Update app to use new column
-- Step 4: Drop old column
ALTER TABLE Users DROP COLUMN OldColumnName;

Validation Strategy

public class MigrationValidator
{
    public async Task<bool> ValidateAsync(string sourceDb, string targetDb)
    {
        // Count validation
        var sourceCount = await CountRecordsAsync(sourceDb);
        var targetCount = await CountRecordsAsync(targetDb);
        
        if (sourceCount != targetCount)
            return false;

        // Data integrity check
        var issues = await CheckDataIntegrityAsync(targetDb);
        if (issues.Any())
        {
            logger.LogError($"Found {issues.Count} integrity issues");
            return false;
        }

        // Performance check
        var queryTime = await MeasureQueryPerformanceAsync(targetDb);
        if (queryTime > TimeSpan.FromSeconds(5))
        {
            logger.LogWarning("Query performance degraded");
            // Decide if acceptable
        }

        return true;
    }
}

Rollback Plan

// Always have rollback procedure ready

public async Task RollbackAsync(string targetDb)
{
    logger.LogInformation("Starting rollback...");
    
    // Switch traffic back to source
    await UpdateConfigAsync("activeDatabase", "source");
    
    // Verify working
    var healthy = await HealthCheckAsync("source");
    if (!healthy)
    {
        logger.LogCritical("Rollback failed - manual intervention needed");
        await AlertOpsTeamAsync();
    }
    
    // Clean up target database
    await DropDatabaseAsync(targetDb);
    logger.LogInformation("Rollback complete");
}

Best Practices

  1. Test extensively: Dry-run before production
  2. Have rollback plan: Always prepared to revert
  3. Validate thoroughly: Check counts, integrity, performance
  4. Communicate clearly: Notify stakeholders
  5. Monitor closely: Watch for issues during migration

Related Concepts

  • Database backups and recovery
  • Transaction logs and point-in-time recovery
  • Feature flags for feature control
  • Monitoring and alerting

Summary

Safe migrations require planning (blue-green or rolling), validation, and rollback capabilities. Test thoroughly before production to prevent data loss and service interruption.