Prisma seed data

Seed a Prisma + PostgreSQL app with FK-intact synthetic data — prisma migrate deploy, then one command. No seed.ts drift.

Prisma apps seed data through prisma/seed.ts — a script that usually grows a hand-written list of prisma.user.create() calls, or a faker-driven factory loop. It works until the schema changes and the seed stops matching it. This guide shows the Prisma-native seeding workflow, where it breaks, and the schema-driven alternative that removes the drift.

How Prisma seeding normally works

Prisma's built-in flow is prisma db seed, which runs the script declared in package.json:

{
  "prisma": {
    "seed": "tsx prisma/seed.ts"
  }
}
// prisma/seed.ts
import { PrismaClient } from "@prisma/client";
import { faker } from "@faker-js/faker";
 
const prisma = new PrismaClient();
 
async function main() {
  for (let i = 0; i < 50; i++) {
    await prisma.user.create({
      data: {
        email: faker.internet.email(),
        name: faker.person.fullName(),
      },
    });
  }
}
 
main();

That works for a standalone users table. The problems start when relations appear.

Where Prisma seed scripts break

Three failure modes, in order of appearance:

  1. Foreign keys. Creating an order requires a user id that doesn't exist yet. You either create the user first and capture the id (fine, but the script now encodes dependency order by hand), or you look it up (prisma.user.findFirst()) — and when the table is empty or the lookup is wrong, the seed silently produces different data than you expect.
  2. Schema drift. Add a NOT NULL column or a relation to User and seed.ts stops compiling or starts producing incomplete rows. Every schema change is a seed change, and the seed is the last file anyone updates.
  3. Uniform randomness. faker.internet.email() is fine for a demo. It is not a distribution: if 70% of your real status values are active, a flat faker loop gives you roughly a third of each, and the query planner behaves differently than it will in production.

Schema-driven seeding with Weavori

Weavori reads the database schema — the same schema Prisma migrated — and generates rows from it. The Prisma-specific workflow:

1. Migrate (or db push) as usual
$ npx prisma migrate deploy
2. Seed from the schema
$ npx --yes @weavori/cli generate postgres://localhost:5432/mydb --rows 1000

Weavori introspects tables, foreign keys, and constraints, resolves the dependency order (parents before children), and writes via COPY. Every generated order.user_id references a real generated user — by construction, not by script logic.

The schema is the seed

When a Prisma migration changes the schema, the generated data changes with it. There is no seed.ts to update because nothing in the script duplicated the schema in the first place.

Prisma + Weavori in CI

The loop that keeps staging and test databases honest:

$ npx prisma migrate deploy
$ npx --yes @weavori/cli generate $TEST_DATABASE_URL --rows 1000 --output plain

Weavori supports API keys for headless auth, standardized exit codes, and offline license validation — CI runners on restricted networks don't phone home. Full GitHub Actions / GitLab / CircleCI / Jenkins examples in the CI/CD guide.

When to keep your Prisma seed

Honesty about boundaries: keep prisma/seed.ts for deterministic unit-test fixtures — a known user with a known email that a test asserts against. @faker-js/faker remains the right tool for single values inside tests. Weavori replaces the dataset problem: filling dev, staging, and CI databases with production-shaped, FK-intact rows.

Ready to generate your first dataset?

Install Weavori in one command and connect to any PostgreSQL database.

$npm install -g @weavori/cli
macOS · Linux · Windows/No dependencies required

No credit card required. Start with a 14-day free trial of Pro, then free tier or subscribe.