db-prisma

Prisma 7 ORM with PostgreSQL — schema design, migrations, seeding, and Railway deployment patterns. This skill should be used when setting up Prisma in a new project, writing migrations, managing database schemas, or deploying Prisma-backed services to Railway.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "db-prisma" with this command: npx skills add aussiegingersnap/cursor-skills/aussiegingersnap-cursor-skills-db-prisma

Prisma Database Skill

Production patterns for Prisma 7 ORM with PostgreSQL, including schema design, versioned migrations, seeding, and Railway-specific configuration.

When to Use This Skill

  • Setting up Prisma in a new project
  • Designing database schemas (models, relations, enums)
  • Writing and running migrations
  • Seeding development databases
  • Deploying Prisma-backed services to Railway
  • Troubleshooting Prisma/PostgreSQL issues

Project Setup

Installation

npm install prisma @prisma/client
npx prisma init --datasource-provider postgresql

Directory Structure

prisma/
  schema.prisma       # Schema definition
  migrations/         # Versioned SQL migrations
  seed.ts             # Database seeder

Environment

# .env (development)
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/myapp?schema=public"

# Railway (production) — auto-wired from Postgres service
DATABASE_URL="postgresql://user:pass@host:port/railway?schema=public&connection_limit=5"

Schema Patterns

Base Schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

Model Conventions

Singular model names, PascalCase. Fields use camelCase. Database columns use snake_case via @map.

model User {
  id        String   @id @default(uuid())
  email     String   @unique
  name      String
  role      Role     @default(MEMBER)
  createdAt DateTime @default(now()) @map("created_at")
  updatedAt DateTime @updatedAt @map("updated_at")

  sessions Session[]
  posts    Post[]

  @@map("user")
}

Timestamps

Every model gets createdAt and updatedAt:

createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")

Enums

enum Role {
  ADMIN
  MEMBER
  GUEST
}

enum Status {
  DRAFT
  PUBLISHED
  ARCHIVED
}

Relations

One-to-Many:

model User {
  id       String    @id @default(uuid())
  posts    Post[]

  @@map("user")
}

model Post {
  id       String   @id @default(uuid())
  title    String
  userId   String   @map("user_id")
  user     User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId])
  @@map("post")
}

Many-to-Many (explicit join table):

model Post {
  id    String     @id @default(uuid())
  tags  PostTag[]

  @@map("post")
}

model Tag {
  id    String     @id @default(uuid())
  name  String     @unique
  posts PostTag[]

  @@map("tag")
}

model PostTag {
  postId String @map("post_id")
  tagId  String @map("tag_id")
  post   Post   @relation(fields: [postId], references: [id], onDelete: Cascade)
  tag    Tag    @relation(fields: [tagId], references: [id], onDelete: Cascade)

  @@id([postId, tagId])
  @@map("post_tag")
}

Indexes

model User {
  id    String @id @default(uuid())
  email String @unique
  name  String

  @@index([name])
  @@map("user")
}

PostgreSQL-Specific Types

model Product {
  id       String   @id @default(uuid())
  metadata Json?
  tags     String[]
  price    Decimal  @db.Decimal(10, 2)

  @@map("product")
}

Migration Workflow

Development

# Create migration from schema changes
npx prisma migrate dev --name add_user_table

# Apply without creating (schema push for prototyping)
npx prisma db push

# Reset database (drops all data)
npx prisma migrate reset

# Check migration status
npx prisma migrate status

Production (Railway)

# Deploy pending migrations (non-interactive, no data loss prompts)
npx prisma migrate deploy

Key Rules

  1. Never edit existing migrations — they may have run in production
  2. Always review generated SQL before committing
  3. Use migrate dev locally, migrate deploy in CI/production
  4. Commit the migrations/ directory — it's your migration history
  5. Use db push only for prototyping — no migration history

Client Usage

Generate Client

npx prisma generate

Run after every schema change. The build command should include this.

Basic CRUD

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// Create
const user = await prisma.user.create({
  data: { email: 'user@example.com', name: 'John' },
});

// Read one
const found = await prisma.user.findUnique({
  where: { email: 'user@example.com' },
});

// Read many with filter
const users = await prisma.user.findMany({
  where: { role: 'MEMBER' },
  orderBy: { createdAt: 'desc' },
  take: 10,
});

// Update
await prisma.user.update({
  where: { id: user.id },
  data: { name: 'Jane' },
});

// Delete
await prisma.user.delete({ where: { id: user.id } });

Relations

// Include relations
const userWithPosts = await prisma.user.findUnique({
  where: { id: userId },
  include: { posts: true, sessions: true },
});

// Nested create
const user = await prisma.user.create({
  data: {
    email: 'user@example.com',
    name: 'John',
    posts: {
      create: [
        { title: 'First Post' },
        { title: 'Second Post' },
      ],
    },
  },
  include: { posts: true },
});

// Select specific fields
const emails = await prisma.user.findMany({
  select: { id: true, email: true },
});

Transactions

const [user, post] = await prisma.$transaction([
  prisma.user.create({ data: { email: 'a@b.com', name: 'A' } }),
  prisma.post.create({ data: { title: 'Hello', userId: 'known-id' } }),
]);

// Interactive transaction
await prisma.$transaction(async (tx) => {
  const user = await tx.user.create({
    data: { email: 'a@b.com', name: 'A' },
  });
  await tx.post.create({
    data: { title: 'Hello', userId: user.id },
  });
});

Seeding

seed.ts

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
  await prisma.user.upsert({
    where: { email: 'admin@example.com' },
    update: {},
    create: {
      email: 'admin@example.com',
      name: 'Admin',
      role: 'ADMIN',
    },
  });

  console.log('Seed complete');
}

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

package.json config

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

Run seed

npx prisma db seed

Seed runs automatically after prisma migrate reset.

Railway Deployment

Connection String

Railway Postgres provides DATABASE_URL automatically when the backend service references the Postgres service. Append connection pooling for production:

DATABASE_URL="postgresql://user:pass@host:port/railway?schema=public&connection_limit=5"

Build Command

npx prisma generate && npx prisma migrate deploy && npm run build

This sequence:

  1. Generates the Prisma client
  2. Applies any pending migrations
  3. Builds the application

railway.toml

[build]
builder = "nixpacks"
buildCommand = "npx prisma generate && npx prisma migrate deploy && npm run build"

[deploy]
startCommand = "node dist/main.js"
healthcheckPath = "/health"
healthcheckTimeout = 300
restartPolicyType = "ON_FAILURE"
restartPolicyMaxRetries = 10

Prisma Studio

npx prisma studio

Opens a browser-based GUI for viewing and editing data at http://localhost:5555.

Package Scripts

{
  "scripts": {
    "db:generate": "prisma generate",
    "db:migrate": "prisma migrate dev",
    "db:migrate:deploy": "prisma migrate deploy",
    "db:push": "prisma db push",
    "db:reset": "prisma migrate reset",
    "db:seed": "prisma db seed",
    "db:studio": "prisma studio"
  }
}

Troubleshooting

"Can't reach database server"

Check DATABASE_URL is set and Postgres is running:

echo $DATABASE_URL
docker compose ps  # if using Docker locally

"Migration failed"

Check migration status and logs:

npx prisma migrate status
npx prisma migrate resolve --rolled-back <migration-name>

"Prisma Client not generated"

Run generate after schema changes:

npx prisma generate

Connection pool exhaustion on Railway

Append &connection_limit=5 to DATABASE_URL. Railway instances have limited connections.

Type errors after schema change

Regenerate client and restart TypeScript server:

npx prisma generate
# Restart TS server in IDE: Cmd+Shift+P → "TypeScript: Restart TS Server"

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

tools-repo-review

No summary provided by upstream source.

Repository SourceNeeds Review
General

ui-principles

No summary provided by upstream source.

Repository SourceNeeds Review
General

db-postgres

No summary provided by upstream source.

Repository SourceNeeds Review