Implement Database Migration System for Schema Evolution

Resolved 💬 2 comments Opened Oct 20, 2025 by sanchitmonga22 Closed Oct 20, 2025

Priority

LOW

Context

Database migrations enable safe schema evolution as the SDK evolves. The iOS SDK has migration support for Core Data. The Kotlin SDK (using Room on Android) needs proper migration infrastructure.

Current State

  • Status: No migration system exists
  • Impact: Breaking changes on SDK updates
  • iOS Has: Migration infrastructure for data persistence

iOS Reference Implementation

  • Migrations: Core Data migration support

Implementation Plan

1. Define Migration Interfaces (commonMain)

// commonMain/kotlin/com/runanywhere/sdk/data/migrations/Migration.kt
interface Migration {
    val fromVersion: Int
    val toVersion: Int
    suspend fun migrate()
}

class MigrationManager {
    
    private val migrations = mutableListOf<Migration>()
    
    fun addMigration(migration: Migration) {
        migrations.add(migration)
    }
    
    suspend fun migrate(currentVersion: Int, targetVersion: Int) {
        val path = findMigrationPath(currentVersion, targetVersion)
        
        for (migration in path) {
            migration.migrate()
        }
    }
    
    private fun findMigrationPath(from: Int, to: Int): List<Migration> {
        // Find sequential migration path
        val path = mutableListOf<Migration>()
        var current = from
        
        while (current < to) {
            val next = migrations.find { it.fromVersion == current }
                ?: throw IllegalStateException("No migration from version $current")
            
            path.add(next)
            current = next.toVersion
        }
        
        return path
    }
}

2. Android Room Migrations (androidMain)

// androidMain/kotlin/com/runanywhere/sdk/data/migrations/RoomMigrations.kt
val MIGRATION_1_2 = object : androidx.room.migration.Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        // Add new column to models table
        database.execSQL("ALTER TABLE models ADD COLUMN version TEXT")
    }
}

val MIGRATION_2_3 = object : androidx.room.migration.Migration(2, 3) {
    override fun migrate(database: SupportSQLiteDatabase) {
        // Add analytics table
        database.execSQL("""
            CREATE TABLE IF NOT EXISTS analytics (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                event_name TEXT NOT NULL,
                timestamp INTEGER NOT NULL
            )
        """.trimIndent())
    }
}

Files to Create/Modify

New Files (commonMain)

  • [ ] data/migrations/Migration.kt
  • [ ] data/migrations/MigrationManager.kt

New Files (androidMain)

  • [ ] data/migrations/RoomMigrations.kt

Files to Modify

  • [ ] data/local/AppDatabase.kt (add migrations to Room)

Success Criteria

  • [ ] Migrations execute in correct order
  • [ ] Data is preserved during migration
  • [ ] Rollback support
  • [ ] Well-tested migration paths

Estimated Effort

3-5 days

🤖 Generated with Claude Code

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗