Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Typeorm Migrations

ASecurity

Creating TypeORM database migrations. Use when schema changes are needed (new columns, tables, indexes, constraints).

33 stars
0 votes
0 copies
0 views
Added 9/20/2026
databasestypescriptgobashsqlexpressdockergitdatabasebackend

Works with

mcp

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add ayunis-core/ayunis-core --skill typeorm-migrations --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Typeorm Migrations?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Typeorm Migrations
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ayunis-core-typeorm-migrations/badge)](https://www.skillsdirectory.com/skills/ayunis-core-typeorm-migrations)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: typeorm-migrations
description: Creating TypeORM database migrations. Use when schema changes are needed (new columns, tables, indexes, constraints).
---

# TypeORM Database Migrations

## Golden Rule

**Never write migration files by hand.** Always auto-generate them from TypeORM entity changes. Never edit a generated migration — if it's wrong, fix the entity and regenerate.

## Entity Rules — The Source of Truth

TypeORM entities (Records) are the **single source of truth** for the database schema. Everything must be expressed through decorators. If a constraint, index, or FK exists in the database but not in an entity decorator, TypeORM will try to drop it on the next `migration:generate`.

### Relations define constraints, not loading behavior

`@ManyToOne` creates a **foreign key constraint** in the database. It does NOT mean the relation is eagerly loaded — relations are lazy by default. You control loading per-query via `relations: { ... }`.

**Always define `@ManyToOne` when a column references another table**, even if you never load the relation object:

```typescript
// CORRECT — column + relation = FK constraint in DB
@Column({ name: 'integration_id', type: 'varchar' })
integrationId: string;

@ManyToOne(() => McpIntegrationRecord, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'integration_id' })
integration: McpIntegrationRecord;

// WRONG — plain column = no FK, no referential integrity
@Column({ name: 'integration_id', type: 'varchar' })
integrationId: string;
```

### All constraints must use decorators

| DB concept | Decorator |
| --- | --- |
| Foreign key | `@ManyToOne` / `@OneToOne` + `@JoinColumn` |
| Unique constraint (full) | `@Unique([...])` on class |
| Unique constraint (partial) | `@Index([...], { unique: true, where: '...' })` on class |
| Check constraint | `@Check('name', 'expression')` on class |
| Index | `@Index()` on property or `@Index([...])` on class |
| Enum column | `@Column({ type: 'enum', enum: MyEnum })` |

**Partial unique indexes** (with `WHERE` clause) cannot use `@Unique` — use `@Index` with `unique: true` and `where` instead.

If you add a value to a TypeScript enum used in `@Column({ type: 'enum' })`, you **must** generate a migration.

### Never hand-write constraint names

TypeORM generates deterministic constraint/index names. Hand-written names (e.g. `FK_my_custom_name`) will mismatch, causing perpetual drift.

## Workflow

### 1. Modify the Entity

Change the record file. Extend `BaseRecord` for `id`, `createdAt`, `updatedAt`:

```typescript
@Entity('agents')
export class AgentRecord extends BaseRecord {
  @Column({ type: 'varchar', length: 255, nullable: true })
  marketplaceSlug: string | null;
}
```

### 2. Generate the Migration

The dev stack must be running (`./dev status`).

```bash
pnpm run migration:generate:dev src/db/migrations/DescriptiveMigrationName
```

> **No `--` before the path.** pnpm forwards the trailing path straight to the script. Adding a `--` separator makes pnpm swallow the path, so TypeORM sees zero arguments and aborts with `Nicht genügend Argumente ohne Optionen: 0 vorhanden, mindestens 1 benötigt` (`ELIFECYCLE Command failed with exit code 1`). Pass the path with no `--`.

### 3. Review the Generated Migration

- Contains **only** the expected changes (no unrelated drift)
- `up()` and `down()` are symmetric
- No hand-written constraint or index names

If the migration contains unexpected drift, the local DB is out of sync. **Rebuild it — do not hand-author a migration to reconcile.** See "Fixing Migration Drift" below.

### 4. Run the Migration

```bash
pnpm run migration:run:dev
```

### 5. Verify Zero Drift

```bash
pnpm run migration:generate:dev src/db/migrations/VerifyNoDrift
```

This **must** print `No changes in database schema were found`. If it generates a file, entities and migrations are still out of sync — investigate before committing.

### 6. Validate

```bash
pnpm exec tsc --noEmit
pnpm run test
```

## Naming Convention

PascalCase describing the change:

| Change | Migration Name |
| --- | --- |
| Add a column | `AddMarketplaceSlugToAgents` |
| Create a table | `CreateTeamSharesTable` |
| Add an index | `AddIndexOnThreadCreatedAt` |
| Remove a column | `RemoveUserShareScope` |
| Add a constraint | `CascadeDeleteSharesOnScopeDelete` |

## Fixing Migration Drift

"Drift" here means: entities on the branch, the migration files, and the local Postgres schema no longer agree. Typical triggers:

- Switching between branches whose migration sets diverge (slot's Postgres volume was written by branch A, you're now on branch B).
- `pnpm run migration:generate:dev` produces surprise changes (removes/renames on things you never touched, or resurrects columns).
- Backend refuses to start with errors like `error: relation "<table>" already exists` (PG code `42P07`) or `column "..." of relation "..." does not exist`.

**Rule: rebuild the database from scratch. Do not hand-author a reconciliation migration.** Hand-written reconciliation migrations poison the migration history for every teammate and every future deploy — they are worse than the drift they were meant to fix.

### The rebuild

Shut the stack down and spin the DB up on an empty volume, then let migrations replay from zero:

```bash
# 1. Shut the stack down completely (from any worktree)
./dev down

# 2. Wipe the slot's Postgres volume so ./dev up starts from an empty DB.
#    Without -v the volume survives and the drift returns immediately.
docker compose -p ayunis-dev-<SLOT> down -v

# 3. Bring the stack back up — ./dev up replays every migration from scratch
./dev up --slot <SLOT>

# 4. Optional: reseed fixtures (see seed-database skill)
cd ayunis-core-backend && pnpm run seed:minimal:ts
```

`<SLOT>` is the slot number this worktree uses — the same one you passed to `./dev up`. See the `dev-environment` skill for slot conventions.

### After the rebuild

Verify zero drift before making further changes:

```bash
cd ayunis-core-backend
pnpm run migration:generate:dev src/db/migrations/VerifyNoDrift
# Must print: "No changes in database schema were found"
```

If a `VerifyNoDrift` file *is* produced, entities and migrations are genuinely out of sync — that's a legitimate migration to *generate* (via TypeORM), not to hand-write. Investigate which entity changed and, if the fix belongs in an earlier migration, edit *that* migration's entity source, not the reconciliation file.

## Anti-Patterns

| Don't | Why | Instead |
| --- | --- | --- |
| Write migration SQL by hand | Drift between entities and schema | Modify the entity, then auto-generate |
| Hand-author a migration to reconcile drift | Poisons migration history for teammates and deploys | Rebuild the DB (`./dev down` + wipe volume + `./dev up`) |
| Edit a generated migration | Constraint names will mismatch | Fix the entity and regenerate |
| Hand-write FK/index/constraint names | Perpetual drift on future generates | Let TypeORM name everything |
| Use `@Column` for a FK without `@ManyToOne` | No FK in the database, no referential integrity | Add `@ManyToOne` + `@JoinColumn` |
| Add enum values without a migration | DB enum won't match TypeScript enum | Generate a migration after adding values |
| Use `@Unique` for partial constraints | Produces full constraint, not partial | Use `@Index({ unique: true, where: '...' })` |
| Skip zero-drift verification | Entities and migrations may still be misaligned | Always verify after running |
| Commit without running | May fail at runtime | Always `migration:run:dev` first |

Attribution

ayunis-coreayunis-core
View sourceMore from ayunis-core →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Mysql Best Practices

MySQL development best practices for schema design, query optimization, and database administration

2481 votes

Clickhouse Io

ClickHouse数据库模式、查询优化、分析和数据工程最佳实践,适用于高性能分析工作负载。

2456590 votes

Jpa Patterns

Spring Boot中的JPA/Hibernate实体设计、关系、查询优化、事务、审计、索引、分页和连接池模式。

2456590 votes

Postgres Patterns

基于Supabase最佳实践的PostgreSQL数据库模式,用于查询优化、架构设计、索引和安全。

2456590 votes

V3 Memory Unification

Unify 6+ memory systems into AgentDB with HNSW indexing for 150x-12,500x search improvements. Implements ADR-006 (Unified Memory Service) and ADR-009 (Hybrid Memory Backend).

701370 votes
View all in databases →