Isaac.

database

Data Migration Strategies

Plan and execute safe database migrations in production.

By Emem IsaacApril 24, 20223 min read
#database#migration#data#schema change#production
Share:

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.

Share:

Written by Emem Isaac

Expert Software Engineer with 15+ years of experience building scalable enterprise applications. Specialized in ASP.NET Core, Azure, Docker, and modern web development. Passionate about sharing knowledge and helping developers grow.

Ready to Build Something Amazing?

Let's discuss your project and explore how my expertise can help you achieve your goals. Free consultation available.

💼 Trusted by 50+ companies worldwide | ⚡ Average response time: 24 hours