Assists Prisma with migration tooling similar to other js ORMS, like Knex
Prisma Migrations is a Node.js library and CLI tool that provides a Knex-like migration management approach for Prisma ORM. Write migrations with familiar up
and down
functions while leveraging Prisma's powerful client and type safety.
- Familiar Knex-like API -
up
anddown
functions you already know - TypeScript First - Full type safety for your migrations
- Prisma Powered - Use both raw SQL and Prisma operations
- Flexible Control - Run specific migrations, rollback, dry-run
- Modern Build - ESM/CJS dual support, Node.js 20+ ready
Prisma's native migration system is excellent for schema-driven development, but it lacks:
- No rollback functionality - Once applied, migrations can't be easily undone
- Limited programmatic control - Can't run specific numbers of migrations or rollback steps
- No up/down functions - Migrations are pure SQL, no TypeScript/JavaScript logic
- Schema-only approach - Difficult to mix schema changes with data seeding/transformation
- No granular migration management - Can't easily target specific migrations or preview changes
This library complements Prisma by providing the migration management patterns developers expect from other ORMs like Knex, while still leveraging Prisma's powerful client and type safety.
npm install prisma-migrations
This library is designed to work with modern versions of Prisma and Node.js. Please ensure your environment meets these requirements:
- Prisma: 2.0.0 or higher
- Node.js: 20.0.0 or higher
- Prisma Client: 4.0.0+ (peer dependency)
- Prisma CLI: 2.0.0+ (peer dependency)
- Node.js: 20.x, 21.x, 22.x, 23.x, 24.x
- CommonJS CLI: Works with Prisma 2.0.0+
- ESM CLI: Works with Prisma 3.15.0+ (requires ES module support)
- Library API: Both ESM and CommonJS builds available
- CommonJS CLI (
dist/cli.cjs
) is used by default for maximum compatibility - ESM CLI (
dist/cli.js
) available for users with compatible Prisma versions - TypeScript migrations require
tsx
to be installed - Development and testing: Node.js 24+ is required for unit tests and mocking
- Manages git-related actions.
- Methods:
getCurrentCommit()
: Retrieve current commit.getCurrentBranch()
: Retrieve current branch.getCommitsBetween(from, to)
: Get commits between references.
- Manages version-based migrations.
- Methods:
registerVersion(version, migrations)
: Register a version.getMigrationsBetween(from, to)
: Determine migrations to run or rollback.generateDeploymentPlan(fromVersion, toVersion)
: Generate a plan between versions.
- VersionMigrationMapping: Information associated with migrations for a version.
- VersionMigrationOptions: Options for managing versions.
- VersionMigrationResult: Result structure for version operations.
# Create a new migration
prisma-migrations create add_users_table
# Run all pending migrations
prisma-migrations up
# Run migrations with options
prisma-migrations up --steps 3
prisma-migrations up --dry-run
# Rollback migrations
prisma-migrations down
prisma-migrations down --steps 2
# Check migration status
prisma-migrations status
import { MigrationManager } from "prisma-migrations";
const manager = new MigrationManager();
// Create a new migration
await manager.createMigration({ name: "add_users_table" });
// Run all pending migrations
await manager.runMigrations();
// Rollback last migration
await manager.rollbackMigrations();
// Get migration status
const status = await manager.getMigrationStatus();
Write migrations with familiar up
and down
functions, just like Knex:
import { PrismaClient } from "@prisma/client";
export async function up(prisma: PrismaClient): Promise<void> {
// Raw SQL for schema changes
await prisma.$executeRaw`
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`;
// Use Prisma operations for data seeding
await prisma.user.createMany({
data: [
{ email: "admin@example.com", name: "Admin User" },
{ email: "user@example.com", name: "Test User" },
],
});
}
export async function down(prisma: PrismaClient): Promise<void> {
await prisma.$executeRaw`DROP TABLE IF EXISTS users`;
}
JavaScript migrations work too:
exports.up = async function (prisma) {
await prisma.$executeRaw`
CREATE TABLE posts (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
user_id INTEGER REFERENCES users(id)
)
`;
};
exports.down = async function (prisma) {
await prisma.$executeRaw`DROP TABLE IF EXISTS posts`;
};
Prisma Migrations can be configured in several ways:
{
"prismaMigrations": {
"migrationsDir": "./migrations",
"schemaPath": "./prisma/schema.prisma",
"tableName": "_prisma_migrations",
"createTable": true,
"migrationFormat": "ts",
"extension": ".ts"
}
}
module.exports = {
migrationsDir: "./migrations",
schemaPath: "./prisma/schema.prisma",
tableName: "_prisma_migrations",
createTable: true,
migrationFormat: "ts", // 'sql', 'js', or 'ts'
extension: ".ts", // or '.js', '.sql'
};
Option | Type | Default | Description |
---|---|---|---|
migrationsDir |
string |
'./migrations' |
Directory where migration files are stored |
schemaPath |
string |
'./prisma/schema.prisma' |
Path to Prisma schema file |
tableName |
string |
'_prisma_migrations' |
Name of the migrations tracking table |
createTable |
boolean |
true |
Whether to auto-create the migrations table |
migrationFormat |
'sql'|'js'|'ts' |
'ts' |
Format for new migration files |
extension |
string |
'.ts' |
File extension for new migrations |
Set DATABASE_URL
environment variable for database connection.
Create a new migration file.
Parameters:
<name>
: Migration name (string)
Example:
prisma-migrations create add_users_table
prisma-migrations create "update user schema"
Run all pending migrations or specific migrations.
Options:
-t, --to <timestamp>
: Run up to a specific migration-s, --steps <number>
: Run a specific number of migrations-d, --dry-run
: Preview migrations without applying
Examples:
# Run all pending migrations
prisma-migrations up
# Run up to a specific migration
prisma-migrations up --to 20231201120000
# Run next 3 migrations
prisma-migrations up --steps 3
# Preview without applying
prisma-migrations up --dry-run
Rollback migrations.
Options:
-t, --to <timestamp>
: Rollback to a specific migration-s, --steps <number>
: Rollback a specific number of migrations-d, --dry-run
: Preview rollback without applying
Examples:
# Rollback last migration
prisma-migrations down
# Rollback to a specific migration
prisma-migrations down --to 20231201120000
# Rollback last 2 migrations
prisma-migrations down --steps 2
# Preview rollback
prisma-migrations down --dry-run
Get the status of all migrations.
Example:
prisma-migrations status
Output:
add_users_table [applied] - 2023-12-01T12:00:00.000Z
add_posts_table [pending] - Pending
update_users_schema [applied] - 2023-12-01T13:00:00.000Z
Test database connection.
Example:
prisma-migrations test
Main class for managing migrations programmatically.
Parameters:
configPath?
: Optional path to configuration file (string)
Example:
import { MigrationManager } from "prisma-migrations";
const manager = new MigrationManager("./custom-config.js");
Create a new migration file.
Parameters:
options
: CreateMigrationOptions objectname
: Migration name (string)directory?
: Optional custom directory (string)template?
: Optional custom template (MigrationTemplate)
Returns: Promise<MigrationFile>
Example:
const migration = await manager.createMigration({
name: "add_users_table",
template: {
up: "CREATE TABLE users (id SERIAL PRIMARY KEY);",
down: "DROP TABLE users;",
},
});
Run pending migrations.
Parameters:
options?
: RunMigrationOptions objectto?
: Run up to specific migration (string)steps?
: Number of migrations to run (number)dryRun?
: Preview without applying (boolean)force?
: Force run even if already applied (boolean)
Returns: Promise<MigrationResult>
Example:
// Run all pending migrations
const result = await manager.runMigrations();
// Run with options
const result = await manager.runMigrations({
steps: 3,
dryRun: true,
});
Rollback applied migrations.
Parameters:
options?
: RollbackMigrationOptions objectto?
: Rollback to specific migration (string)steps?
: Number of migrations to rollback (number)dryRun?
: Preview without applying (boolean)force?
: Force rollback even without down script (boolean)
Returns: Promise<MigrationResult>
Example:
// Rollback last migration
const result = await manager.rollbackMigrations();
// Rollback with options
const result = await manager.rollbackMigrations({
steps: 2,
dryRun: true,
});
Get status of all migrations.
Returns: Promise<MigrationStatus[]>
Example:
const statuses = await manager.getMigrationStatus();
statuses.forEach((status) => {
console.log(`${status.name} [${status.status}]`);
});
Get detailed migration state information.
Returns: Promise<MigrationState>
Example:
const state = await manager.getMigrationState();
console.log("Applied:", state.applied.length);
console.log("Pending:", state.pending.length);
Test database connection.
Returns: Promise<boolean>
Example:
const isConnected = await manager.testConnection();
if (isConnected) {
console.log("Database connection successful");
}
Manages configuration loading and access.
Methods:
getConfig()
: Get current configurationupdateConfig(updates)
: Update configurationgetDatabaseUrl()
: Get database URL from various sources
Manages migration file operations.
Methods:
createMigrationFile(name, template?)
: Create new migration filereadMigrationFiles()
: Read all migration filesgetMigrationFile(timestamp)
: Get specific migration filegetMigrationByName(name)
: Find migration by nameparseMigrationContent(content)
: Parse UP/DOWN sections
Handles database operations and migration tracking.
Methods:
connect()
: Connect to databasedisconnect()
: Disconnect from databasegetAppliedMigrations()
: Get all applied migrationsrecordMigration(id, name)
: Record migration as appliedremoveMigration(id)
: Remove migration recordexecuteMigration(sql)
: Execute migration SQL
interface MigrationConfig {
migrationsDir: string;
schemaPath: string;
databaseUrl?: string;
tableName?: string;
createTable?: boolean;
}
interface Migration {
id: string;
name: string;
filename: string;
timestamp: Date;
applied: boolean;
appliedAt?: Date;
rollback?: string;
}
interface MigrationResult {
success: boolean;
migrations: Migration[];
error?: string;
}
interface MigrationStatus {
id: string;
name: string;
status: "pending" | "applied" | "error";
appliedAt?: Date;
error?: string;
}
Prisma Migrations supports both SQL and JavaScript/TypeScript migration files:
-- UP
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- DOWN
DROP TABLE users;
TypeScript (.ts files):
import { PrismaClient } from "@prisma/client";
export async function up(prisma: PrismaClient): Promise<void> {
// Raw SQL approach
await prisma.$executeRaw`
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`;
// Or use Prisma operations for data seeding
await prisma.user.createMany({
data: [{ email: "admin@example.com" }, { email: "user@example.com" }],
});
}
export async function down(prisma: PrismaClient): Promise<void> {
await prisma.$executeRaw`DROP TABLE IF EXISTS users`;
}
JavaScript (.js files):
exports.up = async function (prisma) {
await prisma.$executeRaw`
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`;
};
exports.down = async function (prisma) {
await prisma.$executeRaw`DROP TABLE IF EXISTS users`;
};
Set the migration format in your configuration:
// prisma-migrations.config.js
module.exports = {
migrationFormat: "ts", // 'sql', 'js', or 'ts'
migrationsDir: "./migrations",
// ... other options
};
Note: TypeScript migrations require tsx
to be installed:
npm install tsx
Manage migrations using git commits or semantic versioning for deployment and rollback scenarios.
// Deploy to specific commit
const manager = new MigrationManager();
const commitSha = "abc123";
const migrations = await manager.getMigrationsByCommit(commitSha);
await manager.runMigrations({ to: migrations[migrations.length - 1].id });
// Rollback to previous commit
const previousCommit = "def456";
const targetMigrations = await manager.getMigrationsByCommit(previousCommit);
await manager.rollbackMigrations({
to: targetMigrations[targetMigrations.length - 1].id,
});
// Register version with migrations
const manager = new MigrationManager();
await manager.registerVersion("1.2.0", ["20231201120000", "20231201130000"]);
// Deploy to version
await manager.deployToVersion("1.2.0");
// Rollback to previous version
await manager.rollbackToVersion("1.1.0");
# Deploy to git commit
prisma-migrations up --commit abc123
# Rollback to commit
prisma-migrations down --commit def456
# Deploy to version
prisma-migrations up --version 1.2.0
# Rollback to version
prisma-migrations down --version 1.1.0
Use Corepack to manage Yarn and ensure you have the latest Node and npm.
corepack enable
npm install
npm run build
- Build the TypeScript sourcenpm test
- Run unit testsnpm run test:docker
- Run end-to-end tests in Dockernpm run lint
- Run oxlint on source codenpm run format
- Format code with prettier
Use npm run
commands for task execution.