Migrations & Seeding

Schema Changes That Travel With Your Code

Migrations & Seeding

Migrations record schema changes as code so every environment lands at the same state. Seeds prime your dev database with useful data.

4 min read Level 3/5 #nestjs#typeorm#migrations
What you'll learn
  • Generate migrations from entity diffs
  • Run migrations in production
  • Seed data for dev

synchronize: true is fine for the first afternoon of a project. After that, you need migrations — versioned, reviewable, reversible scripts that describe how the schema changes over time.

A Standalone DataSource

The TypeORM CLI needs a config file it can load without booting Nest. Create a datasource.ts next to your entities:

import { DataSource } from 'typeorm';
import { config } from 'dotenv';

config();

export default new DataSource({
  type: 'postgres',
  host: process.env.DB_HOST,
  port: Number(process.env.DB_PORT),
  username: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME,
  entities: ['src/**/*.entity.ts'],
  migrations: ['src/migrations/*.ts'],
});

This same DataSource is also what forRoot would build at runtime, so the two stay in sync.

Generate a Migration

After changing an entity, point the CLI at the DataSource and it’ll diff your entities against the current schema:

typeorm-ts-node-commonjs migration:generate \
  ./src/migrations/AddBioToUser -d ./src/datasource.ts

You’ll get a file with up() and down() methods. Read it before committing — the generator is good but not perfect, especially around column renames (it usually sees them as drop + add).

Run Migrations

typeorm-ts-node-commonjs migration:run -d ./src/datasource.ts
typeorm-ts-node-commonjs migration:revert -d ./src/datasource.ts

In production, run migrations as a step before booting the app — or set migrationsRun: true on the DataSource if you’re comfortable with boot-time migrations. Either way, never set synchronize: true in prod.

Seeding

TypeORM doesn’t ship a seeding command, but a tiny TS script does the job:

// scripts/seed.ts
import dataSource from '../src/datasource';
import { User } from '../src/users/user.entity';

async function main() {
  await dataSource.initialize();
  const repo = dataSource.getRepository(User);
  await repo.save([
    { email: 'admin@example.com', name: 'Admin' },
    { email: 'user@example.com', name: 'User' },
  ]);
  await dataSource.destroy();
}

main();

Run it with ts-node scripts/seed.ts. Keep seeds idempotent — your teammates will run them more than once.

Prisma in NestJS →