Drizzle vs Prisma в 2026: бенчмарки, DX и где какой выбирать
Сравнения Drizzle и Prisma я для себя делал дважды: в 2024-м, когда переводил один проект, и в 2026-м, когда переводил второй. За эти полтора года Prisma подтянулась, Drizzle тоже подрос, и однозначного победителя нет. Но картинка стала заметно чётче, и теперь я могу довольно уверенно сказать, в каких сценариях беру что.
В тексте — личные замеры на одном и том же сервисе и личные впечатления от работы с обоими. Версии: Prisma 5.18, Drizzle ORM 0.30, drizzle-kit 0.21, Postgres 16, Node 20, на бенче — небольшой VPS у российского хостера, 4 CPU/8 GB.
Что меряю и зачем
Один и тот же эндпоинт API: получить ленту постов с автором, лайками и тегами, страница 50 записей. То есть один основной select, два join и одно подзапросное агрегирование. Под нагрузкой — вызовы из autocannon в течение 30 секунд, 50 параллельных соединений. Pg-pool: 10. Меряю медиану, p95 и количество запросов, ушедших в БД, через pg_stat_statements.
Throughput и latency
Цифры округляю, разброс между запусками ±5%.
- Drizzle (один SQL с join-ами): медиана 11 мс, p95 28 мс, RPS ~3500.
- Prisma (с include): медиана 14 мс, p95 35 мс, RPS ~2700.
- Prisma (с relationLoadStrategy: 'join'): медиана 12 мс, p95 31 мс, RPS ~3200.
Разница не катастрофическая. До перехода на стратегию join у Prisma тут был отдельный запрос на каждую таблицу, и picture получался куда грустнее. В версиях, где этой опции ещё нет, я честно отдавал Drizzle победу. Сейчас разница в основном из-за overhead query engine.
Холодный старт
На serverless и в локальной разработке холодный старт мне важен.
- Drizzle: подтягивает несколько модулей и сразу готов. Импорт ~120 мс на холодную.
- Prisma: запускает query engine (Rust binary). На VPS ~250–400 мс на старте.
Если у тебя cron-задачи в serverless и каждая live несколько секунд, Prisma съедает значимую часть времени. Drizzle тут заметно бодрее.
Размер бандла
Это про edge runtime и lambdas, где каждый мегабайт считают.
- Drizzle, минимально подключённый: ~150–200 KB.
- Prisma client + query engine: ~25 MB на disk, в bundle уезжает значительная часть зависимости от платформы.
Для классического VPS бандл не важен. Для Cloudflare Workers — критично, и Drizzle тут просто без альтернатив (Prisma идёт через отдельный Accelerate-прокси).
Developer experience
Тут уже вкус, и Prisma на коротких задачах сильно удобнее.
Что у Prisma приятно
schema.prismaчитается как документация. Новый человек в проекте за пять минут понимает модель данных.- Studio из коробки. Drizzle Studio догнала, но Prisma Studio выглядит чуть отполированнее.
includeиselectпокрывают 80% запросов одной строкой. Не надо думать о join-условиях.- Миграции через
migrate dev— буквально одна команда, которая и SQL сгенерирует, и накатит, и сидов запустит.
Что у Drizzle приятно
- Схема — обычный TS. Нет генерации клиента после каждого изменения. Поправил поле — IDE сразу подсветила все места, где этот тип используется.
- SQL-builder тонкий и предсказуемый. То, что я пишу в TS, видно в логах БД почти один в один.
- Миграции — обычные SQL-файлы. Их можно прочитать в PR и понять, что меняется. С Prisma на больших командах это превращалось в холивар «а можно ли руками править миграцию».
- Нет отдельного бинаря query engine. На редких архитектурах (ARM, alpine) с Prisma я нередко ловил «бинарь не подходит для платформы».
Сложные запросы
Когда запрос выходит за пределы CRUD, картина меняется. У меня в одном проекте был отчёт с пятью CTE и оконными функциями. На Prisma я честно перешёл на $queryRaw и потерял типы. Drizzle такие штуки отлично описывает встроенным sql с тегированными литералами, и тип результата я указываю явно — но без потери остальной типизации запроса.
import { sql } from 'drizzle-orm';
const rows = await db.execute<{ day: string; total: number }>(sql`
with daily as (
select date_trunc('day', published_at) as day, count(*) as total
from posts
where author_id = ${authorId}
group by 1
)
select day::text as day, total::int as total
from daily
order by day desc
limit 30
`);В Prisma такой код тоже возможен через $queryRaw, но интеграция с остальной кодовой базой получается заметно более рваной.
Миграции на больших проектах
Случай из жизни: переименовать колонку с миграцией данных. На Prisma этот сценарий до сих пор отдельная морока: сначала нужно сломать prisma migrate в одну сторону, потом руками править SQL, потом удалять снапшот. На Drizzle ты редактируешь сгенерированный SQL ровно как обычный SQL-файл и накатываешь как обычно. Для команды, у которой DBA читает каждое изменение схемы, это решает.
Где я беру Prisma
- Стартап-MVP, важна скорость в первый месяц.
- Продукт с CRUD-моделью, которой долгое время не нужны нестандартные запросы.
- Команда, в которой большинство пишет на TS и не хочет писать SQL.
- Большая часть запросов — простые select по id или поиск по индексам.
Где я беру Drizzle
- Edge или serverless с маленьким бандлом.
- Сервис, где BI-сторона запросов сложнее CRUD: отчёты, ETL, аналитика.
- Проект, в котором руками подкручиваются индексы и план запроса важнее, чем экономия пары часов на схему.
- Команда, где DBA читает миграции и хочет чистый SQL в репо.
- Долгоживущий бэкенд, в котором не хочется зависеть от Rust-бинаря и его обновлений.
Выводы
Prisma больше про скорость старта. Drizzle больше про контроль. Если на твоём проекте оба варианта упираются в пограничные сценарии — реальные нагрузочные замеры решат за тебя. У меня сейчас на новых сервисах Drizzle просто потому, что я не хочу платить за query engine на каждом инстансе и хочу видеть SQL в логах. Но на проектах с быстрым продуктовым циклом я бы и сегодня не стал отговаривать команду от Prisma — за пару недель работы выигрыш окупает потерю на переходе.