Database Migrations in TypeScript: A Complete Guide to Tools and Approaches

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Database Migrations in TypeScript: How to Manage Schema Without Pain

Developing in TypeScript requires not only strict code typing but also reliable management of the database structure. Migrations are a way to version database schema changes, allowing the team to synchronize the database state with the application code. In this article, we will review the main libraries for migrations in TypeScript projects, their features, and provide practical examples.



What are migrations and why are they needed?

A migration is a file with instructions describing changes to the database schema (creating, modifying, or deleting tables, indexes, relationships). Benefits of using migrations:

  • Versioning — each change is recorded in a separate file with a timestamp or number.
  • Reproducibility — you can deploy the database from scratch at any version.
  • Teamwork — all developers apply the same changes.
  • Rollback — the ability to undo unsuccessful changes.


Popular tools for migrations in TypeScript



1. TypeORM

TypeORM is an ORM that works with TypeScript and JavaScript. The built-in migration system is based on the command line.

Installation:

npm install typeorm reflect-metadatanpm install @types/node --save-dev

Example of generating a migration:

npx typeorm migration:create src/migration/AddUserTable

Example migration code:

import { MigrationInterface, QueryRunner, Table } from "typeorm";

export class AddUserTable1234567890123 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: "name", type: "varchar", length: "255" }, { name: "email", type: "varchar", length: "255", isUnique: true } ] })); }

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

Running migrations:

npx typeorm migration:run

Advantages: tight integration with TypeORM, automatic generation based on entities.

Disadvantages: can be slow for complex projects, requires configuration setup.



2. Prisma

Prisma is a modern ORM with a powerful migration system. It uses a declarative DSL (Prisma Schema Language).

Installation:

npm install prisma @prisma/clientnpx prisma init

Example schema (schema.prisma):

model User {  id    Int     @id @default(autoincrement())  name  String  email String  @unique  posts Post[]}

model Post { id Int @id @default(autoincrement()) title String content String? authorId Int author User @relation(fields: [authorId], references: [id])}

Creating and applying a migration:

npx prisma migrate dev --name init

Prisma automatically creates an SQL file and applies it to the database. You can also check the status:

npx prisma migrate status

Advantages: declarative approach, automatic generation, excellent documentation.

Disadvantages: tied to Prisma, difficult to bypass for special scenarios.



3. Knex.js

Knex.js is a lightweight query builder for Node.js that includes a migration system. It works with TypeScript through add-ons

Recommendations