Data Migration Strategies
Plan and execute safe database migrations in production.
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
- Test extensively: Dry-run before production
- Have rollback plan: Always prepared to revert
- Validate thoroughly: Check counts, integrity, performance
- Communicate clearly: Notify stakeholders
- 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.
Related Articles
Azure Cosmos DB with ASP.NET Core
Build globally distributed applications with Azure Cosmos DB.
Read More databaseDatabase Indexing Fundamentals
Learn how database indexing improves query performance significantly.
Read More databaseDrizzle ORM Getting Started
Build type-safe database queries with Drizzle ORM.
Read More