Execute database migrations across ORMs

Database migration

by wshobson · MIT license · ★ 39,857 on GitHub · updated Sep 21

Database migration cover

Execute database migrations across ORMs and platforms with zero-downtime strategies, data transformation, and rollback procedures. Use when migrating databases, changing schemas, performing data transformations, or implementing…

---
name: database-migration
description: Execute database migrations across ORMs and platforms with zero-downtime strategies, data transformation, and rollback procedures. Use when migrating databases, changing schemas, performing data transformations, or implementing zero-downtime deployment strategies.
---

# Database Migration

Master database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.

## When to Use This Skill

- Migrating between different ORMs
- Performing schema transformations
- Moving data between databases
- Implementing rollback procedures
- Zero-downtime deployments
- Database version upgrades
- Data model refactoring

Overview

Master database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.

Manual install (npx, ZIP)
Claude Codenpx skills add wshobson/agents --skill database-migration -g -a claude-code
Claude Code (manual)mkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/wshobson/agents/tar.gz/4236bb91f839 \ | tar -xz -C ~/.claude/skills --strip-components=4 agents-4236bb91f839/plugins/framework-migration/skills/database-migration
Windows (PowerShell)New-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/544c2cc357f74c1e03e9/database-migration.zip" -OutFile "$env:TEMP\database-migration.zip"; Expand-Archive "$env:TEMP\database-migration.zip" -DestinationPath "$HOME\.claude\skills" -Force
Claude.ai / desktopDownload the ZIP and upload it under Settings → Capabilities → Skills.
Codex, Cursor, other agentsPoint them at SKILL.md. The other files are plain text.

Connects with Agent Alley MCP · agentalley.io/mcp

Files included

  • SKILL.md8.0 KB
  • references/1 file · 1.7 KB
Read the files here
wshobson/4236bb92 files
SKILL.md
Show the full text334 lines

Database Migration

Master database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.

When to Use This Skill

  • Migrating between different ORMs
  • Performing schema transformations
  • Moving data between databases
  • Implementing rollback procedures
  • Zero-downtime deployments
  • Database version upgrades
  • Data model refactoring

ORM Migrations

Sequelize Migrations
// migrations/20231201-create-users.js
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable("users", {
      id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true,
      },
      email: {
        type: Sequelize.STRING,
        unique: true,
        allowNull: false,
      },
      createdAt: Sequelize.DATE,
      updatedAt: Sequelize.DATE,
    });
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable("users");
  },
};

// Run: npx sequelize-cli db:migrate
// Rollback: npx sequelize-cli db:migrate:undo
TypeORM Migrations
// migrations/1701234567-CreateUsers.ts
import { MigrationInterface, QueryRunner, Table } from "typeorm";

export class CreateUsers1701234567 implements MigrationInterface {
  public async up(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.createTable(
      new Table({
        name: "users",
        columns: [
          {
            name: "id",
            type: "int",
            isPrimary: true,
            isGenerated: true,
            generationStrategy: "increment",
          },
          {
            name: "email",
            type: "varchar",
            isUnique: true,
          },
          {
            name: "created_at",
            type: "timestamp",
            default: "CURRENT_TIMESTAMP",
          },
        ],
      }),
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    await queryRunner.dropTable("users");
  }
}

// Run: npm run typeorm migration:run
// Rollback: npm run typeorm migration:revert
Prisma Migrations
// schema.prisma
model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  createdAt DateTime @default(now())
}

// Generate migration: npx prisma migrate dev --name create_users
// Apply: npx prisma migrate deploy

Schema Transformations

Adding Columns with Defaults
// Safe migration: add column with default
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.addColumn("users", "status", {
      type: Sequelize.STRING,
      defaultValue: "active",
      allowNull: false,
    });
  },

  down: async (queryInterface) => {
    await queryInterface.removeColumn("users", "status");
  },
};
Renaming Columns (Zero Downtime)
// Step 1: Add new column
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.addColumn("users", "full_name", {
      type: Sequelize.STRING,
    });

    // Copy data from old column
    await queryInterface.sequelize.query("UPDATE users SET full_name = name");
  },

  down: async (queryInterface) => {
    await queryInterface.removeColumn("users", "full_name");
  },
};

// Step 2: Update application to use new column

// Step 3: Remove old column
module.exports = {
  up: async (queryInterface) => {
    await queryInterface.removeColumn("users", "name");
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.addColumn("users", "name", {
      type: Sequelize.STRING,
    });
  },
};
Changing Column Types
module.exports = {
  up: async (queryInterface, Sequelize) => {
    // For large tables, use multi-step approach

    // 1. Add new column
    await queryInterface.addColumn("users", "age_new", {
      type: Sequelize.INTEGER,
    });

    // 2. Copy and transform data
    await queryInterface.sequelize.query(`
      UPDATE users
      SET age_new = CAST(age AS INTEGER)
      WHERE age IS NOT NULL
    `);

    // 3. Drop old column
    await queryInterface.removeColumn("users", "age");

    // 4. Rename new column
    await queryInterface.renameColumn("users", "age_new", "age");
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.changeColumn("users", "age", {
      type: Sequelize.STRING,
    });
  },
};

Data Transformations

Complex Data Migration
module.exports = {
  up: async (queryInterface, Sequelize) => {
    // Get all records
    const [users] = await queryInterface.sequelize.query(
      "SELECT id, address_string FROM users",
    );

    // Transform each record
    for (const user of users) {
      const addressParts = user.address_string.split(",");

      await queryInterface.sequelize.query(
        `UPDATE users
         SET street = :street,
             city = :city,
             state = :state
         WHERE id = :id`,
        {
          replacements: {
            id: user.id,
            street: addressParts[0]?.trim(),
            city: addressParts[1]?.trim(),
            state: addressParts[2]?.trim(),
          },
        },
      );
    }

    // Drop old column
    await queryInterface.removeColumn("users", "address_string");
  },

  down: async (queryInterface, Sequelize) => {
    // Reconstruct original column
    await queryInterface.addColumn("users", "address_string", {
      type: Sequelize.STRING,
    });

    await queryInterface.sequelize.query(`
      UPDATE users
      SET address_string = CONCAT(street, ', ', city, ', ', state)
    `);

    await queryInterface.removeColumn("users", "street");
    await queryInterface.removeColumn("users", "city");
    await queryInterface.removeColumn("users", "state");
  },
};

Rollback Strategies

Transaction-Based Migrations
module.exports = {
  up: async (queryInterface, Sequelize) => {
    const transaction = await queryInterface.sequelize.transaction();

    try {
      await queryInterface.addColumn(
        "users",
        "verified",
        { type: Sequelize.BOOLEAN, defaultValue: false },
        { transaction },
      );

      await queryInterface.sequelize.query(
        "UPDATE users SET verified = true WHERE email_verified_at IS NOT NULL",
        { transaction },
      );

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      throw error;
    }
  },

  down: async (queryInterface) => {
    await queryInterface.removeColumn("users", "verified");
  },
};
Checkpoint-Based Rollback
module.exports = {
  up: async (queryInterface, Sequelize) => {
    // Create backup table
    await queryInterface.sequelize.query(
      "CREATE TABLE users_backup AS SELECT * FROM users",
    );

    try {
      // Perform migration
      await queryInterface.addColumn("users", "new_field", {
        type: Sequelize.STRING,
      });

      // Verify migration
      const [result] = await queryInterface.sequelize.query(
        "SELECT COUNT(*) as count FROM users WHERE new_field IS NULL",
      );

      if (result[0].count > 0) {
        throw new Error("Migration verification failed");
      }

      // Drop backup
      await queryInterface.dropTable("users_backup");
    } catch (error) {
      // Restore from backup
      await queryInterface.sequelize.query("DROP TABLE users");
      await queryInterface.sequelize.query(
        "CREATE TABLE users AS SELECT * FROM users_backup",
      );
      await queryInterface.dropTable("users_backup");
      throw error;
    }
  },
};

Additional patterns and templates

More detailed templates and worked examples live in references/details.md. Read that file for the full pattern library.

1---
2name: database-migration
3description: Execute database migrations across ORMs and platforms with zero-downtime strategies, data transformation, and rollback procedures. Use when migrating databases, changing schemas, performing data transformations, or implementing zero-downtime deployment strategies.
4---
5 
6# Database Migration
7 
8Master database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.
9 
10## When to Use This Skill
11 
12- Migrating between different ORMs
13- Performing schema transformations
14- Moving data between databases
15- Implementing rollback procedures
16- Zero-downtime deployments
17- Database version upgrades
18- Data model refactoring
19 
20## ORM Migrations
21 
22### Sequelize Migrations
23 
24```javascript
25// migrations/20231201-create-users.js
26module.exports = {
27 up: async (queryInterface, Sequelize) => {
28 await queryInterface.createTable("users", {
29 id: {
30 type: Sequelize.INTEGER,
31 primaryKey: true,
32 autoIncrement: true,
33 },
34 email: {
35 type: Sequelize.STRING,
36 unique: true,
37 allowNull: false,
38 },
39 createdAt: Sequelize.DATE,
40 updatedAt: Sequelize.DATE,
41 });
42 },
43 
44 down: async (queryInterface, Sequelize) => {
45 await queryInterface.dropTable("users");
46 },
47};
48 
49// Run: npx sequelize-cli db:migrate
50// Rollback: npx sequelize-cli db:migrate:undo
51```
52 
53### TypeORM Migrations
54 
55```typescript
56// migrations/1701234567-CreateUsers.ts
57import { MigrationInterface, QueryRunner, Table } from "typeorm";
58 
59export class CreateUsers1701234567 implements MigrationInterface {
60 public async up(queryRunner: QueryRunner): Promise<void> {
61 await queryRunner.createTable(
62 new Table({
63 name: "users",
64 columns: [
65 {
66 name: "id",
67 type: "int",
68 isPrimary: true,
69 isGenerated: true,
70 generationStrategy: "increment",
71 },
72 {
73 name: "email",
74 type: "varchar",
75 isUnique: true,
76 },
77 {
78 name: "created_at",
79 type: "timestamp",
80 default: "CURRENT_TIMESTAMP",
81 },
82 ],
83 }),
84 );
85 }
86 
87 public async down(queryRunner: QueryRunner): Promise<void> {
88 await queryRunner.dropTable("users");
89 }
90}
91 
92// Run: npm run typeorm migration:run
93// Rollback: npm run typeorm migration:revert
94```
95 
96### Prisma Migrations
97 
98```prisma
99// schema.prisma
100model User {
101 id Int @id @default(autoincrement())
102 email String @unique
103 createdAt DateTime @default(now())
104}
105 
106// Generate migration: npx prisma migrate dev --name create_users
107// Apply: npx prisma migrate deploy
108```
109 
110## Schema Transformations
111 
112### Adding Columns with Defaults
113 
114```javascript
115// Safe migration: add column with default
116module.exports = {
117 up: async (queryInterface, Sequelize) => {
118 await queryInterface.addColumn("users", "status", {
119 type: Sequelize.STRING,
120 defaultValue: "active",
121 allowNull: false,
122 });
123 },
124 
125 down: async (queryInterface) => {
126 await queryInterface.removeColumn("users", "status");
127 },
128};
129```
130 
131### Renaming Columns (Zero Downtime)
132 
133```javascript
134// Step 1: Add new column
135module.exports = {
136 up: async (queryInterface, Sequelize) => {
137 await queryInterface.addColumn("users", "full_name", {
138 type: Sequelize.STRING,
139 });
140 
141 // Copy data from old column
142 await queryInterface.sequelize.query("UPDATE users SET full_name = name");
143 },
144 
145 down: async (queryInterface) => {
146 await queryInterface.removeColumn("users", "full_name");
147 },
148};
149 
150// Step 2: Update application to use new column
151 
152// Step 3: Remove old column
153module.exports = {
154 up: async (queryInterface) => {
155 await queryInterface.removeColumn("users", "name");
156 },
157 
158 down: async (queryInterface, Sequelize) => {
159 await queryInterface.addColumn("users", "name", {
160 type: Sequelize.STRING,
161 });
162 },
163};
164```
165 
166### Changing Column Types
167 
168```javascript
169module.exports = {
170 up: async (queryInterface, Sequelize) => {
171 // For large tables, use multi-step approach
172 
173 // 1. Add new column
174 await queryInterface.addColumn("users", "age_new", {
175 type: Sequelize.INTEGER,
176 });
177 
178 // 2. Copy and transform data
179 await queryInterface.sequelize.query(`
180 UPDATE users
181 SET age_new = CAST(age AS INTEGER)
182 WHERE age IS NOT NULL
183 `);
184 
185 // 3. Drop old column
186 await queryInterface.removeColumn("users", "age");
187 
188 // 4. Rename new column
189 await queryInterface.renameColumn("users", "age_new", "age");
190 },
191 
192 down: async (queryInterface, Sequelize) => {
193 await queryInterface.changeColumn("users", "age", {
194 type: Sequelize.STRING,
195 });
196 },
197};
198```
199 
200## Data Transformations
201 
202### Complex Data Migration
203 
204```javascript
205module.exports = {
206 up: async (queryInterface, Sequelize) => {
207 // Get all records
208 const [users] = await queryInterface.sequelize.query(
209 "SELECT id, address_string FROM users",
210 );
211 
212 // Transform each record
213 for (const user of users) {
214 const addressParts = user.address_string.split(",");
215 
216 await queryInterface.sequelize.query(
217 `UPDATE users
218 SET street = :street,
219 city = :city,
220 state = :state
221 WHERE id = :id`,
222 {
223 replacements: {
224 id: user.id,
225 street: addressParts[0]?.trim(),
226 city: addressParts[1]?.trim(),
227 state: addressParts[2]?.trim(),
228 },
229 },
230 );
231 }
232 
233 // Drop old column
234 await queryInterface.removeColumn("users", "address_string");
235 },
236 
237 down: async (queryInterface, Sequelize) => {
238 // Reconstruct original column
239 await queryInterface.addColumn("users", "address_string", {
240 type: Sequelize.STRING,
241 });
242 
243 await queryInterface.sequelize.query(`
244 UPDATE users
245 SET address_string = CONCAT(street, ', ', city, ', ', state)
246 `);
247 
248 await queryInterface.removeColumn("users", "street");
249 await queryInterface.removeColumn("users", "city");
250 await queryInterface.removeColumn("users", "state");
251 },
252};
253```
254 
255## Rollback Strategies
256 
257### Transaction-Based Migrations
258 
259```javascript
260module.exports = {
261 up: async (queryInterface, Sequelize) => {
262 const transaction = await queryInterface.sequelize.transaction();
263 
264 try {
265 await queryInterface.addColumn(
266 "users",
267 "verified",
268 { type: Sequelize.BOOLEAN, defaultValue: false },
269 { transaction },
270 );
271 
272 await queryInterface.sequelize.query(
273 "UPDATE users SET verified = true WHERE email_verified_at IS NOT NULL",
274 { transaction },
275 );
276 
277 await transaction.commit();
278 } catch (error) {
279 await transaction.rollback();
280 throw error;
281 }
282 },
283 
284 down: async (queryInterface) => {
285 await queryInterface.removeColumn("users", "verified");
286 },
287};
288```
289 
290### Checkpoint-Based Rollback
291 
292```javascript
293module.exports = {
294 up: async (queryInterface, Sequelize) => {
295 // Create backup table
296 await queryInterface.sequelize.query(
297 "CREATE TABLE users_backup AS SELECT * FROM users",
298 );
299 
300 try {
301 // Perform migration
302 await queryInterface.addColumn("users", "new_field", {
303 type: Sequelize.STRING,
304 });
305 
306 // Verify migration
307 const [result] = await queryInterface.sequelize.query(
308 "SELECT COUNT(*) as count FROM users WHERE new_field IS NULL",
309 );
310 
311 if (result[0].count > 0) {
312 throw new Error("Migration verification failed");
313 }
314 
315 // Drop backup
316 await queryInterface.dropTable("users_backup");
317 } catch (error) {
318 // Restore from backup
319 await queryInterface.sequelize.query("DROP TABLE users");
320 await queryInterface.sequelize.query(
321 "CREATE TABLE users AS SELECT * FROM users_backup",
322 );
323 await queryInterface.dropTable("users_backup");
324 throw error;
325 }
326 },
327};
328```
329 
330## Additional patterns and templates
331 
332More detailed templates and worked examples live in `references/details.md`. Read that file for the full pattern library.
333 
334 
View all files on GitHub →

Details

Updated
Sep 21, 2026
License
MIT
Stars on the repo
★ 39,857
Checked
Source
wshobson/agents ↗
Creator
wshobson · 179 listings
View creator

Similar skills

See all →
MCPPostgres server with health checksPostgres MCP Procrystaldba/postgres-mcp · by crystaldbaPostgres server with health checks, index tuning and explain plans, with a restricted read-only mode for production.★ 3.3k GitHub starsSkillPostgres best practices maintained by SupabaseSupabase postgres best practicessupabase/agent-skills · by supabasePostgres best practices maintained by Supabase, for Postgres running anywhere. Load this skill BEFORE writing or changing anything that lives in a Postgres database: creating or altering tables and columns (including choosing column types), schema design, migrations and declarative schema files, RLS policies and the tests that verify them, indexes, triggers, database functions, queues and scheduled jobs (pg_cron, pgmq), vector/semantic search (pgvector), and restoring dumps (pg_restore) or importing data. Also load it when diagnosing slow queries, high CPU, timeouts, EXPLAIN plans, connection exhaustion, locking, bloat, or rows visible to the wrong user or tenant. This is not just a performance guide — schema, migration, security, and SQL authoring tasks need these rules too, even for a one-column change or a single query.★ 2.7k GitHub starsSkillDesigns database schemas, indexing strategiesDatabase designCloudAI-X/claude-workflow-v2 · by CloudAI-XDesigns database schemas, indexing strategies, query optimization, and migration patterns for SQL and NoSQL databases. Use when designing tables, optimizing queries, fixing N+1 problems, planning migrations, or when asked about database performance, normalization, ORMs, or data modeling.★ 1.4k GitHub starsSkillOptimize vector index performance for latency, recallVector index tuningwshobson/agents · by wshobsonOptimize vector index performance for latency, recall, and memory. Use when tuning HNSW parameters, selecting quantization strategies, or scaling vector search infrastructure.★ 39.9k GitHub starsSkillDesign database schemas, plan data migrationsDatabase Designer - POWERFUL Tier Skillalirezarezvani/claude-skills · by alirezarezvaniUse when the user asks to design database schemas, plan data migrations, optimize queries, choose between SQL and NoSQL, or model data relationships.★ 26.3k GitHub starsSkillCreate ERD diagrams, normalize database schemasDatabase schema designeralirezarezvani/claude-skills · by alirezarezvaniUse when the user asks to create ERD diagrams, normalize database schemas, design table relationships, or plan schema migrations.★ 26.3k GitHub stars

More from wshobson

SkillMaster C/.NET backend development patterns for buildingwshobson/agents · by wshobsonMaster C#/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications. Covers async/await, dependency injection, Entity Framework Core, Dapper, configuration, caching, and testing with xUnit. Use when developing .NET backends, reviewing C# code, or designing API architectures.★ 39.9k GitHub starsSkillImplement WCAG 2.2 compliant interfaces with mobileAccessibility compliancewshobson/agents · by wshobsonImplement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support. Use when auditing accessibility, implementing ARIA patterns, building for screen readers, or ensuring inclusive user experiences.★ 39.9k GitHub starsSkillMaster Material Design 3 and Jetpack Compose patternsAndroid Mobile Designwshobson/agents · by wshobsonMaster Material Design 3 and Jetpack Compose patterns for building native Android apps. Use when designing Android interfaces, implementing Compose UI, or following Google's Material Design guidelines.★ 39.9k GitHub starsSkillMigrate from AngularJS to Angular using hybrid modeAngular migrationwshobson/agents · by wshobsonMigrate from AngularJS to Angular using hybrid mode, incremental component rewriting, and dependency injection updates. Use when upgrading AngularJS applications, planning framework migrations, or modernizing legacy Angular code.★ 39.9k GitHub starsSkillUnderstand anti-reversing, obfuscationAnti reversing techniqueswshobson/agents · by wshobsonUnderstand anti-reversing, obfuscation, and protection techniques encountered during software analysis. Use this skill when analyzing malware evasion techniques, when implementing anti-debugging protections for CTF challenges, when reverse engineering packed binaries, or when building security research tools that need to detect virtualized environments.★ 39.9k GitHub starsSkillBuild production Apache Airflow DAGs with best practicesApache Airflow DAG Patternswshobson/agents · by wshobsonBuild production Apache Airflow DAGs with best practices for operators, sensors, testing, and deployment. Use when creating data pipelines, orchestrating workflows, or scheduling batch jobs.★ 39.9k GitHub stars