A database-agnostic migration framework for TypeScript and JavaScript projects.
MSR provides a lightweight, flexible framework for managing database migrations without locking you into a specific ORM or database system. Bring your own database implementation and let MSR handle the migration workflow, versioning, validation, and execution.
Enhanced type safety, metrics collection, and multi-format configuration:
- π‘οΈ Generic Type Parameters - Database-specific type safety with
<DB extends IDB>generics throughout the API (BREAKING: type parameters now required) - π Metrics Collection - Built-in collectors for observability with console, JSON, CSV, and logger-based output
- π YAML, TOML, and XML Support - Use your preferred config format (
.yaml,.toml,.xml) alongside JS/JSON - π Plugin Architecture - Extensible loader system with optional peer dependencies keeps core lightweight
- ποΈ Log Level Control - Configurable log levels (
error,warn,info,debug) to control output verbosity - π‘ Better Error Messages - Actionable error messages with installation instructions when formats aren't available
- β¨ 100% Test Coverage - All statements, branches, functions, and lines covered
Important
v0.6.0 contains breaking changes: Type parameters are now required for all interfaces (e.g., IDatabaseMigrationHandler<IDB>) and the constructor signature changed to dependency injection pattern. Migration takes 10-30 minutes. See the v0.5.x β v0.6.0 Migration Guide for step-by-step instructions.
Production-grade transaction management and cloud-native configuration:
- π Transaction Management - Configurable modes (per-migration, per-batch, none) with automatic retry logic and isolation level control
- βοΈ Environment Variables - Complete MSR_* configuration support following 12-factor app principles for Docker, Kubernetes, and CI/CD
- π Enhanced Hooks - Transaction lifecycle hooks for monitoring and metrics collection
- π 100% Backward Compatible - Zero breaking changes from v0.4.x
- π Database Agnostic - Works with any database (SQL, NoSQL, NewSQL) by implementing a simple interface
- π‘οΈ Type Safe - Full TypeScript support with complete type definitions
- πΎ Smart Rollback - Multiple strategies: backup/restore, down() methods, both, or none
- π Transaction Control - Configurable transaction modes with automatic retry and isolation levels (v0.5.0)
- βοΈ Environment Variables - Full 12-factor app configuration support with MSR_* variables (v0.5.0)
- π Multi-Format Config - Support for JS, JSON, YAML, TOML, and XML configuration files (v0.6.0)
- ποΈ Log Level Control - Configurable verbosity (error, warn, info, debug) for different environments (v0.6.0)
- π Migration Tracking - Maintains execution history in your database with checksums
- β Built-in Validation - Detects conflicts, missing files, and integrity issues
- π¨ Multiple Output Formats - ASCII tables, JSON, or silent output
- π Flexible Logging - Console, file, or custom loggers with level-aware filtering (v0.6.0)
- π Metrics Collection - Built-in collectors for monitoring performance and tracking execution (v0.6.0)
- πͺ Lifecycle Hooks - Process, script, backup, and transaction lifecycle hooks (v0.5.0)
- π¦ Library-First Design - Returns structured results, safe for web servers and long-running apps
npm install @migration-script-runner/coreOr with yarn:
yarn add @migration-script-runner/coreimport { IDatabaseMigrationHandler, IDB, ISqlDB } from '@migration-script-runner/core';
// For SQL databases, implement ISqlDB
interface IMyDatabase extends ISqlDB {
query(sql: string): Promise<unknown>;
}
export class MyDatabaseHandler implements IDatabaseMigrationHandler<IMyDatabase> {
db: IMyDatabase;
schemaVersion: ISchemaVersion<IMyDatabase>;
backup?: IBackup<IMyDatabase>;
async checkConnection(): Promise<void> {
await this.db.query('SELECT 1');
}
getName(): string {
return 'My Database Handler';
}
}TypeScript Migration:
// migrations/V202501280100_create_users.ts
import { IRunnableScript, IMigrationInfo, IDB } from '@migration-script-runner/core';
export default class CreateUsers implements IRunnableScript<IDB> {
async up(db: IDB, info: IMigrationInfo): Promise<string> {
await db.query(`
CREATE TABLE users (
id INT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE
)
`);
return 'Users table created';
}
async down(db: IDB): Promise<string> {
await db.query('DROP TABLE users');
return 'Users table dropped';
}
}SQL Migration:
-- migrations/V202501280100_create_users.up.sql
CREATE TABLE users (
id INT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE
);import { MigrationScriptExecutor, Config } from '@migration-script-runner/core';
import { MyDatabaseHandler } from './database-handler';
const config = new Config();
config.folder = './migrations';
config.logLevel = 'info'; // v0.6.0: 'error' | 'warn' | 'info' | 'debug'
const handler = new MyDatabaseHandler();
const executor = new MigrationScriptExecutor<IMyDatabase>({ handler }, config);
// Library usage - returns structured result
const result = await executor.up();
if (result.success) {
console.log(`β
Executed ${result.executed.length} migrations`);
} else {
console.error('β Migration failed:', result.errors);
process.exit(1);
}Quick Config Examples:
# Environment variable configuration (v0.5.0+)
MSR_FOLDER=./migrations
MSR_LOG_LEVEL=debug # v0.6.0: Control output verbosity
# Or use config file (v0.6.0+)
# msr.config.yaml
folder: ./migrations
logLevel: debug # error | warn | info | debugπ Full Documentation - Complete guides, API reference, and examples
- Getting Started Guide - Complete setup walkthrough
- Writing Migrations - Best practices and patterns
- SQL Migrations - Using .sql migration files
- Version Control - Target specific versions
- Configuration - Migration settings, validation, rollback strategies
- Custom Loggers - Console, file, or cloud logging
- Metrics Collection - Built-in collectors for observability and performance monitoring
- Render Strategies - ASCII tables, JSON, or custom formats
- Validation - Custom validation rules
- API Reference - Complete API documentation
- Recipes - Common patterns (PostgreSQL, MongoDB, testing)
- Comparison - Compare with other migration tools
- Version Migration - Upgrade guides between versions
MSR was born from a real problem: In 2017, while building a mobile app with Firebase, a small team needed to backup and restore production data multiple times a week. Manual processes meant constant risk of corrupting critical data before the app even launched. The solution? A JavaScript tool that automated migrations with automatic backups and intelligent rollback.
Six years and many projects later, that prototype became MSR - completely rewritten in TypeScript with a database-agnostic architecture. The core insight: migration tools should be as flexible as your stack. Whether you're migrating Firebase collections or PostgreSQL tables, using SQL files or TypeScript logic, MSR adapts to your needs instead of forcing you into rigid patterns.
Today, MSR powers migrations across multiple database platforms with features traditional tools don't offer: built-in backup/restore, polyglot migrations (SQL + TypeScript + JavaScript), custom validators, transaction control, and deep customization. It's designed for real-world scenarios where you need both the simplicity of SQL migrations and the power of programmatic logic.
Read the full origin story β
Bring your own database. MSR doesn't lock you into a specific ORM or database system. Whether you're using PostgreSQL, MongoDB, DynamoDB, or a custom database, MSR handles the migration workflow while you maintain full control.
Perfect for:
- π Any database system (SQL, NoSQL, NewSQL, or custom)
- π― Production applications (returns structured results instead of calling
process.exit()) - π‘οΈ Type-safe migrations with full TypeScript support
- π¦ Library or CLI usage in web servers, workers, or serverless functions
- β‘ Flexible workflows with multiple rollback strategies and lifecycle hooks
- π³ Container deployments with environment variable configuration (v0.5.0)
What makes MSR different:
- Library-first design - Safe for web servers and long-running applications
- True database agnosticism - No SQL assumptions, works with any database
- Production-grade transactions - Configurable modes with automatic retry and isolation control (v0.5.0)
- Cloud-native configuration - Complete environment variable support for Docker/Kubernetes (v0.5.0)
- Multiple rollback strategies - Choose backup, down() methods, both, or none
- SQL file support - Use
.up.sqland.down.sqlfiles alongside TypeScript migrations - Well tested - 100% code coverage with mutation testing
Contributions are welcome! Please read our Contributing Guide for guidelines on code style, testing requirements, and pull request process.
See our GitHub Issues for tasks that need help.
This project is licensed under the MIT License with Commons Clause and Attribution Requirements.
Note
Quick Summary:
- β Free to use in your applications (including commercial)
- β Free to modify and contribute
- β Cannot sell MSR or database adapters as standalone products
- π Database adapters require attribution
See the LICENSE file or read the License Documentation for detailed examples and FAQ.
- π Documentation: https://migration-script-runner.github.io/msr-core/
- π Issues: https://github.com/migration-script-runner/msr-core/issues
- π¬ Discussions: https://github.com/migration-script-runner/msr-core/discussions
- π¦ npm: https://www.npmjs.com/package/@migration-script-runner/core
By Volodymyr Lavrynovych β’ Created in Ukraine πΊπ¦