Exercise 1: An Idempotent Reference Seed — Possible Solution ============================================================== // prisma/seeds/reference.ts import { prisma } from "../../lib/prisma"; export const REFERENCE_TAGS = ["prisma", "orm", "typescript", "sql", "news"]; export const ADMIN_EMAIL = "admin@blog.local"; export async function seedReference() { await prisma.user.upsert({ where: { email: ADMIN_EMAIL }, update: { role: "ADMIN" }, // repair the role if someone changed it create: { email: ADMIN_EMAIL, name: "Site admin", role: "ADMIN" }, }); for (const name of REFERENCE_TAGS) { await prisma.tag.upsert({ where: { name }, update: {}, create: { name } }); } } // prisma/seed.ts (for now) import { seedReference } from "./seeds/reference"; import { prisma } from "../lib/prisma"; seedReference() .then(async () => { const [users, tags] = await Promise.all([prisma.user.count(), prisma.tag.count()]); console.log({ users, tags }); }) .catch((e) => { console.error(e); process.exitCode = 1; }) .finally(() => prisma.$disconnect()); Running it three times on an empty database: $ npx prisma db seed -> { users: 1, tags: 5 } $ npx prisma db seed -> { users: 1, tags: 5 } $ npx prisma db seed -> { users: 1, tags: 5 } WHY THIS WORKS AS AN ANSWER ------------------------------ Every row is created with upsert keyed on a @unique field (email and tag name), so a second run finds the existing rows instead of hitting P2002. The admin's update block re-applies the one property that matters, so running the seed also repairs drift. Nothing is deleted, which is what makes this file safe to run against production too. The constants are exported so the sample seed (Exercise 2) can avoid touching these rows.