{"dataset":{"id":"00000000-0000-0000-0000-000000000020","slug":"prisma-best-practices","name":"Prisma best practices","description":"Source-linked guidance on Prisma ORM fundamentals: data modeling in the contract file, the migration workflow, relation queries, index configuration, and transactions. Scoped to Prisma ORM 8 (the indexes page covers v7); not a general SQL corpus.","visibility":"public","version":1,"documentCount":5,"publisher":"Koskamo editorial","license":"Original summaries; linked sources retain their own terms.","reviewedAt":"2026-10-04T00:00:00.000Z","readOnly":true,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},"total":5,"documents":[{"title":"Transactions with db.transaction()","sourceUrl":"https://www.prisma.io/docs/orm/prisma-client/queries/transactions","text":"Run several writes as one unit with db.transaction(...): they all commit together, or they all roll back. Prisma ORM 8 runs on PostgreSQL, SQLite, and MongoDB, with no MySQL support; the examples are PostgreSQL, and db.transaction(...) works the same on SQLite. Use a transaction whenever one business operation spans more than one write — creating a user with their first records, moving a value between two rows, or deleting a parent after its children — but you don't need one for a single write, because every mutation is already atomic on its own. Pass a callback to db.transaction(...), and inside it query through tx instead of db: tx.orm is the model API and tx.sql is the SQL query builder, both working the same as db.orm and db.sql, and create(...) takes the fields of the record directly, with no data: wrapper. Every query you make on tx runs inside the transaction, db.transaction(...) returns whatever your callback returns, reads through tx.orm see the rows the transaction has already written, and a helper that runs inside the caller's transaction takes tx as a parameter. Scope: Prisma ORM 8. Reviewed October 4, 2026.","id":"prisma-best-practices:Transactions with db.transaction()","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},{"title":"Index configuration in the schema","sourceUrl":"https://www.prisma.io/docs/orm/prisma-schema/data-model/indexes","text":"Prisma ORM configures database indexes, unique constraints, and primary key constraints through attribute arguments; full text indexes in MySQL and MongoDB are available through the fullTextIndex preview feature using the @@fulltext attribute. The length argument specifies a maximum length for the subpart of the value to be indexed on String and Bytes types — MySQL requires it when the full value would exceed its index size limits — and it is available on the @id, @@id, @unique, @@unique, and @@index attributes, MySQL only. The sort argument specifies the order that entries of the constraint or index are stored: available on @unique, @@unique, and @@index in all databases, and on @id and @@id in SQL Server. The type argument supports index access methods other than PostgreSQL's default BTree — Hash, Gist, Gin, SpGist, and Brin — on the @@index attribute, PostgreSQL only. The clustered argument configures whether a constraint or index is clustered, on all five attributes, SQL Server only, and the map argument specifies a custom name for the index or constraint in the underlying database, supported in all databases. Scope: Prisma ORM v7. Reviewed October 4, 2026.","id":"prisma-best-practices:Index configuration in the schema","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},{"title":"Relation queries with .include()","sourceUrl":"https://www.prisma.io/docs/orm/prisma-client/queries/relation-queries","text":"Read related records in the same query by adding .include(...) to the query chain, as in db.orm.public.Post.where({ published: true }).include(\"author\").all(). Related records come back nested on the parent, with types matching your models. On PostgreSQL the path is db.orm.<schema>.<ModelName>; the schema is public unless you wrap the model in a namespace block. The last call in the awaited chain says what you want back: .all() returns every matching record as an array, and .first() returns one record or null. .where(...) takes two forms: an object matching fields to exact values, or a callback for comparisons such as .where((p) => p.title.like(\"Hello%\")), and chaining .where(...) twice requires both to match. Pass .include(...) the relation field name from your contract, not a table name; it fetches the relation in the same query as the parent — one SQL statement, reading the relation with a correlated subquery — and replaces Prisma ORM 7's include: { author: true }. Use .include(...) when the caller needs the related data in the same response, and skip it when the foreign key already on the record is enough. Scope: Prisma ORM 8. Reviewed October 4, 2026.","id":"prisma-best-practices:Relation queries with .include()","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},{"title":"Applying migrations with db migrate","sourceUrl":"https://www.prisma.io/docs/orm/prisma-migrate/workflows/development-and-production","text":"Plan migrations with npx prisma migration plan, then apply them with npx prisma db migrate, which runs them against a database until that database matches your contract; it replaces Prisma ORM 7's prisma migrate deploy and works on PostgreSQL and MongoDB, with SQLite still experimental. Prisma ORM decides what to run by comparing two records: each version of your contract.prisma file is a contract state, and the database stores a marker recording which contract state it matches. db migrate reads the marker and runs the migrations from that state to the contract you last emitted with npx prisma contract emit, and a successful run shows each migration's operations and the marker it wrote. The db commands connect using db.connection in prisma.config.ts; pass --db with a connection string to target a different database such as production. A warning symbol marks a destructive operation, such as setting NOT NULL, and db migrate applies destructive operations without stopping to ask, so review them first with npx prisma migration show <dir> before applying migrations to staging or production. Scope: Prisma ORM 8. Reviewed October 4, 2026.","id":"prisma-best-practices:Applying migrations with db migrate","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"},{"title":"Models and the contract file","sourceUrl":"https://www.prisma.io/docs/orm/prisma-schema/data-model/models","text":"In Prisma ORM 8 you define your data structure in your contract, the contract.prisma file that replaced schema.prisma; Prisma ORM derives both your TypeScript types and your migrations from it. There is no datasource or generator block any more, because the connection string has moved to prisma.config.ts. A contract is built from four building blocks: models, primary keys, scalar fields, and relations. Declare a model with the model keyword and give it fields, as in model User { id Int @id @default(autoincrement()) email String name String? }. On a relational database a model becomes a table; on MongoDB it becomes a collection, and the primary key is the document's mandatory _id field, which must be an ObjectId — @map(\"_id\") gives the field that name in the database. Give every model a primary key marked with @id, because update and delete fail at runtime on a model that has neither a primary key nor a unique field. A natural key is a value that already identifies the record in the real world; use one when it is stable and unique. Scope: Prisma ORM 8. Reviewed October 4, 2026.","id":"prisma-best-practices:Models and the contract file","version":1,"createdAt":"2026-10-04T00:00:00.000Z","updatedAt":"2026-10-04T00:00:00.000Z"}]}