Prisma Seed File Builder

Generate a Prisma seed.ts file with sample data for development

Builds a TypeScript Prisma seed file with upsert operations for each model, realistic sample records, a main() function, PrismaClient lifecycle, and try/catch error handling — wired for prisma db seed. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

Why use upsert instead of create?

upsert is idempotent: running the seed twice updates existing rows instead of inserting duplicates or throwing a unique-constraint error. That makes the file safe to re-run during development.

Generate a re-runnable Prisma seed file

A good seed file gives every developer the same realistic data after a fresh migrate reset. Writing it by hand means repeating PrismaClient setup, looping to create rows, and wrapping everything so a failure does not leave a dangling connection. This builder produces a complete, idempotent seed.ts from a short description of your models.

Why idempotency matters for seed files

A seed file that uses create() instead of upsert() throws a unique-constraint error the second time it runs — which happens every time a developer runs prisma migrate reset. The fix is upsert(): it matches on a unique field (the where clause) and either creates a new row or updates the existing one. Re-running the seed is safe regardless of how many times it has run before.

This is especially important in CI environments where databases are frequently reset and re-seeded as part of test setup. An idempotent seed also means developers never need to manually truncate tables to get a clean state — prisma migrate reset handles it.

How it works

For each model you list with its fields, the builder emits an upsert inside a loop. The first field you list becomes the unique match key — it must be @id or @unique in your schema.

The generated file follows a standard structure:

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
  for (let i = 1; i <= 5; i++) {
    await prisma.user.upsert({
      where: { email: `user-${i}@example.com` },
      update: { name: `User ${i}` },
      create: {
        email: `user-${i}@example.com`,
        name: `User ${i}`,
      },
    })
  }
}

main()
  .catch((e) => { console.error(e); process.exit(1) })
  .finally(async () => { await prisma.$disconnect() })

Field values are inferred from the field name and type — strings get readable text, numbers get an index-based integer, booleans alternate, and dates use new Date(). Relation fields are left as a clearly marked TODO because they require real foreign keys from the seeded parent records.

Wiring up the seed command

Add the seed configuration to package.json once:

{
  "prisma": {
    "seed": "tsx prisma/seed.ts"
  }
}

After that, npx prisma db seed runs the file explicitly, and npx prisma migrate reset runs it automatically after resetting the database. Use tsx (from the tsx npm package) rather than ts-node for faster TypeScript execution without a separate compilation step.

Tips and notes

Seed parent models before child models so foreign keys exist when you fill in the relation TODOs — the seed order in the file matters. Keep the $disconnect() in finally — leaving the client open can hang the process or exhaust the connection pool in CI. For large seed datasets, use createMany() rather than looping upsert() — it is significantly faster because it batches inserts rather than issuing one query per row.