Где держать базу данных — Postgres на Neon
Ты собрал MVP. Файл prisma/dev.db лежит рядом с кодом, всё работает. Деплоишь на сервер — и через неделю обнаруживаешь: контейнер пересоздался, файл с базой стёрся, юзеры пропали. Или: запустил второй инстанс приложения для нагрузки — у каждого инстанса своя БД, юзеры видят разные данные. Или просто: 50 человек одновременно зашли на сайт, SQLite заблокировался, всё упало. Это не страшилки — это реальные сценарии того, почему файловая БД рядом с приложением — для разработки, не для людей в интернете.
Почему SQLite — это для разработки, а не продакшна
SQLite — это не сервер, это ОДИН файл с расширением .db. Все запросы идут через файловые операции операционной системы. Плюсы для разработки: ничего не настраивать, скопировал файл — скопировал базу. Минусы для продакшна: если контейнер умер — файл умер вместе с ним. Если два процесса пишут одновременно — один блокирует другой. Если масштабируешься на несколько серверов — каждый сервер думает, что у него своя база. Бэкапов автоматических нет, репликации нет, удалённого доступа нет. Для локалки и тестов — топ. Для тысячи юзеров — катастрофа, ждущая своего часа.
PostgreSQL и почему именно он
PostgreSQL — это полноценная база-сервер. Запускается отдельным процессом (часто на отдельной машине), приложение подключается по сети. Поддерживает тысячи одновременных соединений, репликацию, бэкапы, точки восстановления, сложные запросы, json-поля, расширения для геоданных и поиска. На нём работают Apple, Spotify, Reddit, Instagram. И что важно для тебя — Prisma поддерживает Postgres как первоклассный язык. Переезд с SQLite на Postgres — это смена одной строки в schema.prisma и одной миграции.
Где хостить Postgres — и почему Neon
Можно поднять Postgres самому на VPS за $5/мес — но придётся самому делать бэкапы, мониторить, обновлять, чинить. На раннем стартапе это потерянное время. Можно взять managed-сервис — Supabase, Railway, Render, Vercel Postgres, AWS RDS. Конкретно Neon выделяется тем, что он serverless: когда никто не пользуется — БД спит и не тратит твою квоту. Просыпается за ~300мс при первом запросе. Бесплатный план — 0.5 GB storage и 190 compute hours в месяц, этого хватит на несколько тысяч пользователей. Плюс branching: можно создать ветку БД для тестов, как ветку в Git. После Neon обратно не хочется.
Pooled vs Direct — два разных URL и зачем
В Neon тебе дают два connection string. Pooled — с "-pooler" в имени хоста, через PgBouncer. Direct — без него, прямое соединение. Зачем оба? Pooled нужен в продакшне на serverless-платформах вроде Vercel: каждая serverless-функция при старте открывает соединение к БД, и без пулера ты быстро упрёшься в лимит соединений. Pooler группирует короткие соединения в одно длинное. Direct нужен для миграций и Prisma Studio — пулер не пропускает некоторые служебные команды Postgres. Поэтому в .env у тебя DATABASE_URL (pooled) и DIRECT_URL (direct).
Прямо на пальцах: переезд за 10 минут
Шаг 1: регистрируешься на neon.tech, создаёшь проект — выбирай регион ближе к серверу приложения. Шаг 2: копируешь оба URL — pooled и direct. Шаг 3: в .env меняешь DATABASE_URL="file:./dev.db" на pooled URL, добавляешь DIRECT_URL = direct URL. Шаг 4: в schema.prisma меняешь provider = "sqlite" на provider = "postgresql" и добавляешь directUrl = env("DIRECT_URL"). Шаг 5: удаляешь старую папку prisma/migrations (она была под SQLite). Шаг 6: запускаешь
Prisma создаёт схему в Neon. Готово.
Грабли, на которые наступают все
P1012 invalid datasource — провайдер в schema.prisma всё ещё "sqlite". Сохрани файл и попробуй снова. P1013 invalid port number — в connection string остались "..." или другие плейсхолдеры. Проверь, что URL — настоящий, скопированный из Neon целиком. EPERM operation not permitted на Windows — у тебя запущен npm run dev и файл prisma DLL занят. Закрой его перед миграцией: taskkill /F /IM node.exe. Too many connections под нагрузкой — забыл -pooler в DATABASE_URL, переключи на pooled.
// БЫЛО — SQLite, файл рядом с проектом
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
// .env: DATABASE_URL="file:./dev.db"
// СТАЛО — Postgres на Neon, два URL
datasource db {
provider = "postgresql"
url = env("DATABASE_URL") // pooled, для приложения
directUrl = env("DIRECT_URL") // direct, для миграций
}
// .env:
// DATABASE_URL="postgresql://user:pass@host-pooler.neon.tech/db?sslmode=require"
// DIRECT_URL="postgresql://user:pass@host.neon.tech/db?sslmode=require"
// Бонус: что Postgres даёт нового по сравнению с SQLite
model User {
id String @id @default(cuid())
email String @unique
level UserLevel @default(intermediate) // настоящие enum'ы
bio String? @db.Text // длинный текст без лимита
}
enum UserLevel {
beginner
intermediate
advanced
}schema.prisma — было / стало