Prisma nails the schema and the client. Data is the part it leaves to you. The official answer is prisma db seed, and all that command does is run a TypeScript file you write and keep up to date by hand. That file is where the pain lives.
The default: a seed.ts you maintain by hand
You wire it up in package.json and write the script:
// package.json
"prisma": { "seed": "tsx prisma/seed.ts" }
// prisma/seed.ts
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
const user = await prisma.user.create({
data: { email: "ada@example.com", name: "Ada" },
});
const post = await prisma.post.create({
data: { title: "Hello", authorId: user.id },
});
await prisma.comment.create({
data: { body: "Nice", postId: post.id, authorId: user.id },
});
}
main().finally(() => prisma.$disconnect());
For three rows this is fine. For a realistic database it turns into a second codebase, and it has three failure modes that never go away:
- You order the inserts by hand. User before post, post before comment. You are topologically sorting your own schema in your head, and one wrong order is a foreign key error at runtime.
- It drifts from the schema. Add a required field or a new relation in
schema.prismaand the seed script breaks until you go back and patch everycreate()by hand. - The distribution is fake. A loop that gives every user exactly five posts is not what production looks like. The long tail, the user with two hundred comments, is exactly where your pagination and N+1 bugs hide, and a uniform loop hides them.
The Snaplet gap
The popular escape hatch was Snaplet: it read your schema and generated seed data, so you did not write the script. In 2025 Snaplet shut down its data product, which left a lot of Prisma teams on an abandoned dependency and back to hand-writing seed.ts. The need did not go away, the tool did. (We wrote up the migration angle in SeedBase vs Snaplet Seed.)
What you actually want
The seed data should fall out of the schema you already wrote. Hand a tool your schema.prisma and get back a database where every relation resolves, inserts come out parent-first, and the shape looks like real life, without you describing any of it row by row. That is what SeedBase does.
1. Point it at your schema
SeedBase reads schema.prisma directly, models, fields, enums and @relation directives included:
model User {
id Int @id @default(autoincrement())
email String @unique
name String
posts Post[]
comments Comment[]
}
model Post {
id Int @id @default(autoincrement())
title String
author User @relation(fields: [authorId], references: [id])
authorId Int
comments Comment[]
}
model Comment {
id Int @id @default(autoincrement())
body String
post Post @relation(fields: [postId], references: [id])
postId Int
author User @relation(fields: [authorId], references: [id])
authorId Int
}
2. Generate and pull the data
Create a project from the schema, generate, and pull the result as SQL (or CSV / JSON). Every authorId and postId points at a row that was actually generated, users come out before posts, posts before comments, so it loads with constraints enabled:
# load the generated seed straight into your database
psql "$DATABASE_URL" -f seedbase-<id>.sql
From the VS Code or JetBrains plugin it is one step: the connection string is auto-detected from your schema.prisma datasource block, and Load into Database (or Reset & Reseed) runs it for you without leaving the editor.
3. Keep prisma db seed if you like it
You do not have to drop the command. Point its script at the generated SQL instead of a hand-maintained seed.ts, and prisma db seed keeps working, it just stops being a file you edit by hand every time the schema changes.
seed.ts is fine, keep it. This earns its place when your schema is relational and you want a realistic, populated database without babysitting a script. SeedBase was tested against a real 20-app project with 226 tables, which is where the relation ordering and distribution handling came from. EU-hosted, no third-party trackers, export everything, so you are never locked in the way the Snaplet shutdown taught everyone to fear.
FAQ
Do I still need a prisma/seed.ts file?
No. You stop hand-writing create() calls. Generate a dataset from your schema, pull it as SQL and load it, or load it straight into your database from the editor plugin. If you like the prisma db seed command, point its script at the generated SQL instead of a hand-maintained seed.ts.
Does SeedBase read my schema.prisma directly?
Yes. It parses schema.prisma, the models, fields, enums and @relation directives, and generates a referentially consistent dataset where parent rows are inserted before the children that reference them, so it loads with foreign key constraints enabled.
Is this a Snaplet seed replacement?
It fills the same gap: generate seed data from your schema instead of writing and maintaining a script. Snaplet shut down its data product in 2025. SeedBase is maintained and EU-hosted, and you can export everything, so there is no lock-in. More in SeedBase vs Snaplet Seed.
Is the seed data deterministic for CI?
Yes. Generation is seeded, so the same seed reproduces the same rows, and a CI pipeline gets a stable, reproducible dataset on every run.
Seed Prisma from your schema, not a script
Point SeedBase at your schema.prisma and generate a populated, relation-consistent database with realistic distributions. Free tier, no credit card.
- Reads schema.prisma
- Every relation resolves
- SQL / CSV / JSON
- EU-hosted
More: Prisma test data · vs Snaplet Seed · why Faker breaks on FKs