Настройка PostgreSQL и MongoDB в Payload CMS
Payload 2.x поддерживает два адаптера БД: PostgreSQL через Drizzle ORM и MongoDB через Mongoose. Выбор влияет на схему хранения данных, возможности запросов и производительность.
PostgreSQL через Drizzle ORM
npm install @payloadcms/db-postgres
// payload.config.ts
import { postgresAdapter } from '@payloadcms/db-postgres'
export default buildConfig({
db: postgresAdapter({
pool: {
connectionString: process.env.DATABASE_URL,
// Или явные параметры:
host: 'localhost',
port: 5432,
database: 'payload_db',
user: 'payload',
password: process.env.DB_PASSWORD,
max: 20, // максимум соединений в пуле
idleTimeoutMillis: 30000,
},
push: false, // не пушить schema в production (использовать миграции)
migrationDir: './migrations',
}),
})
Миграции Drizzle:
# Сгенерировать миграцию после изменения коллекций
npx payload migrate:create
# Применить миграции
npx payload migrate
# Откат
npx payload migrate:down
# Статус
npx payload migrate:status
Миграции сохраняются в ./migrations/*.ts — можно редактировать вручную для сложных изменений схемы.
Схема хранения в PostgreSQL:
-- Для коллекции posts Payload создаёт таблицы:
SELECT table_name FROM information_schema.tables
WHERE table_name LIKE 'posts%';
-- posts — основные данные
-- posts_rels — связи (relationship fields)
-- posts_locales — локализованные поля (если включены)
-- _posts_v — версии (если включено versioning)
-- _posts_v_locales — версии локализованных полей
Прямые запросы через Drizzle:
import { getPayload } from 'payload'
import config from '@payload-config'
const payload = await getPayload({ config })
const drizzle = payload.db.drizzle // прямой доступ к Drizzle instance
// Raw SQL запрос
const result = await drizzle.execute(
sql`SELECT p.*, COUNT(c.id) as comment_count
FROM posts p
LEFT JOIN comments c ON c.post_id = p.id
WHERE p.status = 'published'
GROUP BY p.id
ORDER BY comment_count DESC
LIMIT 10`
)
MongoDB через Mongoose
npm install @payloadcms/db-mongodb
import { mongooseAdapter } from '@payloadcms/db-mongodb'
export default buildConfig({
db: mongooseAdapter({
url: process.env.MONGODB_URI!,
// Опции подключения
connectOptions: {
maxPoolSize: 10,
serverSelectionTimeoutMS: 5000,
},
}),
})
Прямой доступ к Mongoose:
const payload = await getPayload({ config })
const mongoose = payload.db.mongoose // mongoose instance
// Нативный запрос MongoDB
const result = await mongoose.connection.db
.collection('posts')
.aggregate([
{ $match: { status: 'published' } },
{ $group: { _id: '$category', count: { $sum: 1 } } },
{ $sort: { count: -1 } },
])
.toArray()
Сравнение адаптеров
| Критерий | PostgreSQL | MongoDB |
|---|---|---|
| Сложные связи | Лучше (JOIN) | Через $lookup |
| Схема | Строгая, миграции | Гибкая |
| Версионирование | Отдельные таблицы _v |
Отдельные коллекции |
| Локализация | _locales таблицы |
Вложенный объект |
| Хостинг | Supabase, Neon, Railway | MongoDB Atlas |
| Production рекомендация | Да, для структурированных данных | Да, для гибких схем |
Переключение адаптеров
Переключить адаптер после запуска в production без миграции данных невозможно напрямую — нужен экспорт/импорт через Payload API. Выбор делается на старте проекта.
Настройка для production
// PostgreSQL в production — через SSL и connection pooling
db: postgresAdapter({
pool: {
connectionString: process.env.DATABASE_URL,
ssl: { rejectUnauthorized: true },
max: 10,
},
push: false, // ОБЯЗАТЕЛЬНО false в production
})
// Или через PgBouncer/Supabase Pooler
// connectionString: 'postgresql://user:[email protected]:6543/postgres?pgbouncer=true'
Сроки
Первоначальная настройка БД-адаптера с миграциями — 0,5 дня. Оптимизация запросов и индексов для production — 1 день.







