* chore: uncomment unified migration * chore: adapt and fix tests * chore: dynamically bump max conns if needed during migration * chore: copilot suggestions * chore: pass ctx in RegisterMigration * chore: make playlists opt-out and dashboards opt-in * chore: adjust dashboard test * chore: disable enable log in test * chore: address review comments - do not use pointer config - add migration registry * chore: more consistent naming * chore: fix playlist discovery test
Unified storage data migrations
Automated migration system for moving Grafana resources from legacy SQL storage to unified storage.
Overview
The migration system transfers resources from legacy SQL tables to Grafana's unified storage backend. It runs automatically during Grafana startup and validates data integrity after each migration.
Supported resources
| Resource | API Group | Legacy table |
|---|---|---|
| Folders | folder.grafana.app |
dashboard |
| Dashboards | dashboard.grafana.app |
dashboard |
| Library panels | dashboard.grafana.app |
library_element |
| Playlists | playlist.grafana.app |
playlist |
Architecture
┌─────────────────────────────────────────────────────────────┐
│ ResourceMigration │
│ (Orchestrates per-organization migration) │
└──────────────────────────┬──────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
UnifiedMigrator Validators BulkProcess API
(Stream legacy (Validate after (Write to unified
resources) migration) storage)
Components
service.go: Migration service entry point and registrationmigrator.go: Core migration logic using streaming BulkProcess APIresource_migration.go: Per-organization migration executionvalidator.go: Post-migration validation (CountValidator, FolderTreeValidator)resources.go: Registry of migratable resource types
How migrations work
Migration flow
- Grafana starts and checks migration status in
unifiedstorage_migration_logtable - For each organization, the migrator:
- Reads resources from legacy SQL tables
- Streams resources to unified storage via BulkProcess API
- Runs validators to verify data integrity
- Records migration result in
unifiedstorage_migration_logtable
Per-organization execution
Migrations run independently for each organization using namespace format org-{orgId}.
Validators
CountValidator
Compares resource counts between legacy SQL and unified storage. Accounts for rejected items during validation.
FolderTreeValidator
Verifies folder parent-child relationships are preserved after migration.
Configuration
To enable migrations, set the following in your Grafana configuration:
[unified_storage]
disable_data_migrations = false
Monitoring
Log messages
Successful migration:
info: storage.unified.resource_migration Starting migration for all organizations
info: storage.unified.resource_migration Migration completed successfully for all organizations
Failed migration:
error: storage.unified.resource_migration Migration validation failed
Migration status
Query the migration log table to check status:
SELECT * FROM unifiedstorage_migration_log WHERE migration_id LIKE '%folders-dashboards%';
The migration_id is defined in service.go during registration. Ideally, it should be the resource type(s) being migrated.
Development
Adding a new validator
Implement the Validator interface:
type Validator interface {
Name() string
Validate(ctx context.Context, sess *xorm.Session, response *resourcepb.BulkResponse, log log.Logger) error
}
Register the validator in service.go when creating the ResourceMigration.
Adding a new resource type
- Add the resource definition to
registeredResourcesinresources.go - Implement the migrator function in the
MigrationDashboardAccessorinterface - Register the migration in
service.go