Docs
Features

Database

Multi-database support via Prisma ORM — PostgreSQL, MySQL, and SQLite. Switch providers with one command, type-safe queries, and automated setup.

Supported Databases

DatabaseRecommended for
PostgreSQLProduction (recommended)
MySQLProduction (alternative)
SQLiteLocal development only

SQLite is not suitable for production. Use PostgreSQL or MySQL when deploying.

Switching Providers

# Interactively select a provider and update schema + migrations
npm run db:update-provider

This script (at scripts/update-db-provider.ts) updates the datasource db.provider in schema.prisma and points migrations to the correct folder (migrations-postgresql, migrations-mysql, or migrations-sqlite).

Never edit the provider field in schema.prisma manually — always use npm run db:update-provider.

Configuration

PostgreSQL

# .env
DATABASE_URL="postgresql://user:password@localhost:5432/tikship"
createdb tikship
npx prisma migrate deploy

MySQL

# .env
DATABASE_URL="mysql://user:password@localhost:3306/tikship"
CREATE DATABASE tikship;
npx prisma migrate deploy

SQLite

# .env
DATABASE_URL="file:./dev.db"

SQLite works out of the box — no server setup needed.

Automated Setup

For a clean environment, a single command handles everything:

npm run init

This runs:

  1. db:update-provider — detects provider from DATABASE_URL
  2. db:generate — regenerates the Prisma client
  3. prisma migrate deploy — applies all pending migrations
  4. db:seed — seeds initial data (superuser, sample products)

Prisma Client

All database access goes through the singleton in src/lib/db/prisma.ts:

import { prisma } from '@/lib/db/prisma'

Never instantiate new PrismaClient() elsewhere.

CRUD Examples

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

// Read — prefer select over include for performance
const user = await prisma.user.findUnique({
  where: { id: userId },
  select: { id: true, name: true, email: true },
})

// List + count in one round trip
const [users, total] = await Promise.all([
  prisma.user.findMany({ where, skip, take, orderBy }),
  prisma.user.count({ where }),
])

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

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

Migrations

# Apply pending migrations (production)
npx prisma migrate deploy

# Create and apply a new migration (development)
npx prisma migrate dev

# Reset (drop all tables, re-migrate, re-seed) — development only
npx prisma migrate reset

# Regenerate Prisma client after schema changes
npm run db:generate

Migration SQL files are stored per engine:

prisma/
├── migrations-postgresql/
├── migrations-mysql/
├── migrations-sqlite/
└── schema.prisma

Transactions

Wrap multiple writes in a transaction inside the service layer:

await prisma.$transaction(async (tx) => {
  const user = await tx.user.create({
    data: { email: 'user@example.com' },
  })
  await tx.profile.create({
    data: { userId: user.id, bio: '' },
  })
})

Schema Conventions

  • Always add @@index for fields used in where filters
  • Always specify onDelete on foreign key relations
  • Use cuid() for primary keys
  • New models should follow the same naming and field conventions as existing core models
model Post {
  id          String   @id @default(cuid())
  title       String
  slug        String   @unique
  status      String   @default("draft")
  authorId    String
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  author      AdminUser @relation(fields: [authorId], references: [id], onDelete: Cascade)

  @@index([status])
  @@index([authorId])
}

Seeding

The seed script (prisma/seed.ts) creates the default superuser and sample products:

npm run db:seed

Edit prisma/seed.ts to add your own initial data.

Prisma Studio

Visual browser for your database:

npm run db:studio
# Open http://localhost:5555

Troubleshooting

ProblemFix
Connection refusedEnsure the database server is running
Migration driftRun npx prisma migrate reset
Type errors after schema changeRun npm run db:generate
Unique constraint error (P2002)Check for duplicate values before insert

Next Steps

Database | Tikship