This guide covers the migration from MongoDB to PostgreSQL using Prisma ORM.
-- PostgreSQL Table
CREATE TABLE categories (
id TEXT PRIMARY KEY,
name TEXT UNIQUE NOT NULL,
name_hebrew TEXT NOT NULL,
description TEXT,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP DEFAULT now(),
updated_at TIMESTAMP DEFAULT now()
);
-- PostgreSQL Table
CREATE TABLE cards (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
title_hebrew TEXT NOT NULL,
description TEXT,
image_url TEXT NOT NULL,
image_public_id TEXT NOT NULL,
is_active BOOLEAN DEFAULT true,
category_id TEXT REFERENCES categories(id),
created_by_id TEXT REFERENCES admins(id),
created_at TIMESTAMP DEFAULT now(),
updated_at TIMESTAMP DEFAULT now()
);
-- PostgreSQL Table (Normalized)
CREATE TABLE editable_fields (
id TEXT PRIMARY KEY,
field_id TEXT NOT NULL,
type TEXT NOT NULL,
default_text TEXT NOT NULL,
position_x FLOAT NOT NULL,
position_y FLOAT NOT NULL,
font_size INTEGER DEFAULT 16,
font_family TEXT DEFAULT 'Noto Sans Hebrew',
color TEXT DEFAULT '#000000',
font_weight TEXT DEFAULT 'normal',
text_align TEXT DEFAULT 'right',
card_id TEXT REFERENCES cards(id) ON DELETE CASCADE
);
# Install PostgreSQL
brew install postgresql # macOS
sudo apt-get install postgresql # Ubuntu
# Create database
createdb simcha_cards
docker run --name postgres-simcha \
-e POSTGRES_DB=simcha_cards \
-e POSTGRES_USER=simcha_user \
-e POSTGRES_PASSWORD=simcha_password \
-p 5432:5432 \
-d postgres:15
cd backend
npm install @prisma/client prisma
npm uninstall mongoose
# Initialize Prisma
npx prisma init
# Generate Prisma client
npx prisma generate
# Push schema to database
npx prisma db push
# Run migrations (production)
npx prisma migrate deploy
Update your .env file:
# Replace MongoDB URI with PostgreSQL
DATABASE_URL="postgresql://username:password@localhost:5432/simcha_cards?schema=public"
# Seed new database
npm run db:seed
The API maintains the same response format for frontend compatibility:
// Frontend still receives MongoDB-style IDs
{
"_id": "clp123...", // Prisma CUID
"title": "Card Title",
"category": {
"_id": "clp456...",
"name": "category-name"
}
}
// Before (Mongoose)
const cards = await Card.find({ isActive: true })
.populate('category')
.sort({ createdAt: -1 })
// After (Prisma)
const cards = await prisma.card.findMany({
where: { isActive: true },
include: { category: true },
orderBy: { createdAt: 'desc' }
})
// Prisma connection pooling
const prisma = new PrismaClient({
datasources: {
db: {
url: process.env.DATABASE_URL + "?connection_limit=5&pool_timeout=20"
}
}
})
# Production deployment
npx prisma migrate deploy
npx prisma generate
Connection Errors
# Check PostgreSQL is running
pg_isready -h localhost -p 5432
Schema Sync Issues
# Reset database (development only)
npx prisma migrate reset
Type Errors
# Regenerate Prisma client
npx prisma generate
Indexing
CREATE INDEX idx_cards_category ON cards(category_id);
CREATE INDEX idx_cards_active ON cards(is_active);
Query Optimization
// Use select to limit fields
const cards = await prisma.card.findMany({
select: {
id: true,
title: true,
titleHebrew: true,
category: {
select: {
id: true,
nameHebrew: true
}
}
}
})
# Test database connection
npx prisma db pull
# Validate schema
npx prisma validate
# View data in Prisma Studio
npx prisma studio
The migration maintains full compatibility with the existing frontend while providing better performance, data integrity, and scalability.