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.
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.