Что такое Prisma ORM: схема, миграции и когда её выбирать

Обновлено:

Prisma — это современный ORM (Object-Relational Mapper) для TypeScript и Node.js, который позволяет работать с базами данных через типобезопасный, автогенерируемый клиент. Вместо написания SQL-запросов вручную вы описываете структуру данных в декларативном schema-файле, а Prisma берёт на себя генерацию SQL, миграции и клиентскую библиотеку с полной типизацией. В 2026 году это один из самых популярных инструментов для работы с базами данных в экосистеме Node.js.


Зачем нужен ORM и что решает Prisma

Работа с базами данных «в лоб» через нативные драйверы предполагает написание SQL-запросов в виде строк, ручное маппирование результатов в объекты TypeScript и самостоятельное управление миграциями схемы. Это работает, но плохо масштабируется: строки с SQL не проверяются компилятором, ошибки в маппинге обнаруживаются только в рантайме, а изменения схемы легко приводят к рассинхронизации с кодом.

Традиционные ORM (TypeORM, Sequelize) решают часть проблем, но имеют другие издержки: конфигурация через декораторы и классы создаёт неявные зависимости, миграции требуют ручного внимания, а типизация часто неполная или требует дополнительных усилий.

Prisma предлагает третий путь — schema-first подход с автоматической генерацией всего, что нужно для работы с базой данных.


Основные концепции Prisma

schema.prisma — единственный источник истины

Всё начинается с файла schema.prisma. Он описывает три вещи:

Datasource — подключение к базе данных. Указываете тип базы (PostgreSQL, MySQL, SQLite, MongoDB и другие) и строку подключения.

Generator — что нужно сгенерировать. По умолчанию это Prisma Client для JavaScript/TypeScript.

Models — структура данных. Каждая модель соответствует таблице в реляционной базе данных (или коллекции в MongoDB).

Пример schema.prisma для блог-платформы:

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
  posts     Post[]
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
  createdAt DateTime @default(now())
}

Схема читается как документация. Без знания SQL понятно, что у пользователя есть email, имя и список постов; каждый пост связан с автором через поле authorId.

Prisma Migrate — управление миграциями

После изменения схемы вы запускаете команду, которая создаёт файл SQL-миграции и применяет его к базе данных:

# Создать и применить миграцию в dev-среде
npx prisma migrate dev --name add_user_posts

# Применить накопленные миграции в production
npx prisma migrate deploy

Prisma сама генерирует правильный SQL для PostgreSQL, MySQL или SQLite — вам не нужно писать ALTER TABLE вручную. История миграций хранится в директории prisma/migrations и версионируется вместе с кодом.

Prisma Client — типобезопасный доступ к данным

После изменения схемы вы запускаете генерацию клиента:

npx prisma generate

Клиент создаётся автоматически на основе текущей схемы. В коде вы получаете полностью типизированный объект со всеми вашими моделями:

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

// Создать пользователя
const user = await prisma.user.create({
  data: {
    email: 'alice@example.com',
    name: 'Alice',
  },
})

// Найти все опубликованные посты с авторами
const posts = await prisma.post.findMany({
  where: {
    published: true,
  },
  include: {
    author: true,
  },
  orderBy: {
    createdAt: 'desc',
  },
})

// Обновить пост
const updated = await prisma.post.update({
  where: { id: 1 },
  data: { published: true },
})

Редактор IDE (VS Code, Cursor, WebStorm) автоматически подсказывает доступные поля, операторы фильтрации и опции включения связанных данных. Если вы сделаете опечатку в имени поля — TypeScript укажет на ошибку до запуска кода.


Поддерживаемые базы данных

Prisma работает с широким спектром баз данных:

| База данных | Статус поддержки | |---|---| | PostgreSQL | Полная, основная | | MySQL / MariaDB | Полная | | SQLite | Полная (идеально для разработки) | | MongoDB | Поддерживается (через Prisma with MongoDB) | | Microsoft SQL Server | Поддерживается | | CockroachDB | Поддерживается | | PlanetScale (MySQL-совместимый) | Поддерживается |

Для большинства production-проектов на Node.js основным выбором остаётся PostgreSQL.


Экосистема Prisma: что входит в пакет

Помимо базового ORM, у Prisma есть несколько связанных инструментов.

Prisma Studio

Визуальный редактор базы данных, запускаемый прямо из терминала:

npx prisma studio

Открывается в браузере: позволяет просматривать, фильтровать и редактировать записи во всех таблицах. Удобно для отладки на этапе разработки и для нетехнических членов команды, которым нужно разово отредактировать данные.

Prisma Accelerate

Глобальный connection pooler с встроенным кешированием запросов. Решает проблему «взрывного» роста числа подключений к PostgreSQL при использовании serverless-функций, где каждый cold start создаёт новое подключение.

// С Prisma Accelerate
const prisma = new PrismaClient().$extends(withAccelerate())

const users = await prisma.user.findMany({
  cacheStrategy: {
    ttl: 60,        // кешировать на 60 секунд
    swr: 10,        // stale-while-revalidate
  },
})

Актуально для Vercel, Netlify, AWS Lambda и других serverless-платформ.

Prisma Pulse

Real-time подписки на изменения в базе данных — аналог Change Data Capture. Позволяет реагировать на INSERT, UPDATE, DELETE события без написания триггеров или polling-механизмов.

Prisma Next (2026)

В марте 2026 года Prisma анонсировала следующее поколение инструмента — «Prisma Next» с архитектурой, полностью переписанной на TypeScript. Цель — сделать систему модульной, убрать зависимость от Rust-бинарного query engine (которая увеличивает bundle size), улучшить поддержку Edge-сред и AI-агентов. Финальный релиз ожидается во второй половине 2026 года.


Как начать: пошаговое руководство

Шаг 1: Установка

npm install prisma --save-dev
npm install @prisma/client

Шаг 2: Инициализация

npx prisma init

Создаётся директория prisma/ с файлом schema.prisma и файл .env с заготовкой DATABASE_URL.

Шаг 3: Настройка подключения

В файле .env:

DATABASE_URL="postgresql://username:password@localhost:5432/mydb?schema=public"

Для SQLite (идеально для быстрого старта):

DATABASE_URL="file:./dev.db"

Шаг 4: Описание схемы

Добавьте модели в schema.prisma (пример выше).

Шаг 5: Создание миграции и базы данных

npx prisma migrate dev --name init

Prisma создаст базу данных (если она не существует), сгенерирует SQL-миграцию и применит её.

Шаг 6: Генерация клиента

npx prisma generate

Автоматически запускается после migrate dev, но можно запустить отдельно при изменении схемы без миграции.

Шаг 7: Работа с данными

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

async function main() {
  const user = await prisma.user.create({
    data: { email: 'test@example.com', name: 'Test User' },
  })
  console.log('Created user:', user)
}

main()
  .catch(console.error)
  .finally(() => prisma.$disconnect())

Продвинутые возможности

Транзакции

// Интерактивная транзакция
const result = await prisma.$transaction(async (tx) => {
  const order = await tx.order.create({ data: { ... } })
  await tx.inventory.update({
    where: { productId: order.productId },
    data: { quantity: { decrement: 1 } },
  })
  return order
})

Nested writes (вложенные операции)

// Создать пользователя и его первый пост в одной операции
const userWithPost = await prisma.user.create({
  data: {
    email: 'bob@example.com',
    posts: {
      create: {
        title: 'Hello World',
        published: true,
      },
    },
  },
  include: { posts: true },
})

Raw SQL для сложных запросов

// Когда нужен полный контроль
const result = await prisma.$queryRaw`
  SELECT u.*, COUNT(p.id) as post_count
  FROM "User" u
  LEFT JOIN "Post" p ON p."authorId" = u.id
  GROUP BY u.id
  HAVING COUNT(p.id) > 5
`

Расширения (Extensions)

В последних версиях Prisma поддерживаются расширения для добавления нестандартных возможностей — например, поддержки pgvector для векторного поиска:

import { PrismaClient } from '@prisma/client'
import { withPgVector } from 'prisma-pgvector-extension'

const prisma = new PrismaClient().$extends(withPgVector())

Когда Prisma — правильный выбор

Prisma хорошо работает в следующих сценариях:

Команды, где не все разработчики глубоко знают SQL. Prisma позволяет работать с базой данных без погружения в детали каждого SQL-запроса.

Быстрое прототипирование и стартапы. Декларативная схема + автомиграции + типизированный клиент позволяют быстро итерироваться.

Full-stack приложения на Next.js или Remix. Prisma идеально интегрируется с этими фреймворками, работает в Server Actions и API Routes.

Монолитные и модульные монолиты. Для архитектур, где весь код живёт в одном репозитории, Prisma — очевидный выбор.


Когда Prisma — не лучший выбор

Serverless и Edge без Prisma Accelerate. Бинарный query engine увеличивает размер бандла и холодный старт. Без Accelerate на высоконагруженных serverless-функциях могут возникнуть проблемы с cold start и connection pooling.

Экстремально сложные SQL-запросы. Если ваш проект живёт на сложных аналитических запросах с несколькими уровнями подзапросов и оконными функциями — накладные расходы абстракции Prisma могут стать проблемой. Используйте $queryRaw или рассмотрите Drizzle.

Крайне ограниченные бюджеты по размеру бандла. В IoT или Edge-средах с жёсткими ограничениями по размеру — Drizzle или нативные драйверы будут предпочтительнее.


Бэкап перед prisma migrate deploy

Отдельного внимания заслуживает деплой миграций. Команда prisma migrate deploy применяет накопленные SQL-миграции к production-базе, и некоторые из них необратимы: удаление колонки (DROP COLUMN), таблицы, изменение типа с потерей данных. Prisma при migrate dev предупреждает о потенциально разрушающих изменениях, но migrate deploy выполняет всё молча — он рассчитан на CI/CD и не задаёт вопросов.

Отсюда простое правило: снимайте бэкап непосредственно перед применением миграций, прямо в пайплайне. Для PostgreSQL это pg_dump в плоский формат:

# шаг CI перед деплоем миграций
pg_dump "$DATABASE_URL" --format=plain --no-owner \
  --file "backup-$(date +%Y%m%d_%H%M%S).sql"

npx prisma migrate deploy

Для SQLite достаточно сделать консистентную копию файла (не обычным cp при включённом WAL, а через онлайн-бэкап):

sqlite3 ./prod.db ".backup './backup-$(date +%Y%m%d_%H%M%S).db'"
npx prisma migrate deploy

Так у вас остаётся точка возврата ровно перед изменением схемы: если миграция удалила нужные данные или упала на середине, вы восстановитесь из дампа, а не из вчерашнего ночного бэкапа. Как разворачивать такие дампы обратно — в статье как восстановить базу из бэкапа.

Prisma управляет схемой и запросами, но не отвечает за сохранность данных. Бэкап-дамп нужно где-то хранить и версионировать. Сервис dbsend принимает уже готовые дампы: pg_dump --format=plain (движок postgresql_dump), mysqldump (mysql_dump) и файлы SQLite (sqlite). Он не подключается к вашей БД и не запускает pg_dump сам — дамп создаёте вы (в CI, cron или systemd-таймере), а CLI загружает его и хранит версии:

dbsend backup backup-20260501_120000.sql \
  -d "$DBSEND_DATABASE_ID" -e postgresql_dump -l "pre-migrate deploy"

Каждая загрузка становится версией vN; одинаковые по содержимому дампы дедуплицируются по SHA-256, а на платных планах доступен diff схемы между версиями и алерт, если бэкап не пришёл по расписанию. Практические рецепты автоматизации — бэкап PostgreSQL в S3 и бэкап SQLite без повреждения; про бэкап PostgreSQL отдельно есть лендинг.


Частые вопросы

Нужно ли знать SQL для работы с Prisma?

Базовое понимание реляционных баз данных (что такое таблица, первичный ключ, отношения) желательно. Глубокое знание SQL для большинства операций не нужно — Prisma генерирует SQL за вас. Для сложных аналитических запросов используется $queryRaw.

Как Prisma работает с существующей базой данных?

Используйте команду prisma db pull — она анализирует существующую базу и генерирует schema.prisma. После этого можно начинать работать с Prisma Client.

Можно ли использовать Prisma с MongoDB?

Да, но с ограничениями. Prisma поддерживает MongoDB, но некоторые NoSQL-специфичные возможности (сложные embedded documents, динамические поля) поддерживаются хуже, чем в нативных MongoDB-драйверах. Подробнее о самой базе — в статье что такое MongoDB.

Что лучше: Prisma или TypeORM?

Prisma обеспечивает лучшую типизацию из коробки, более понятный синтаксис и стабильные миграции. TypeORM ближе к паттерну Active Record и лучше знаком разработчикам с фоном в Java/C#. Для новых проектов на TypeScript Prisma предпочтительнее. Сравнение с ещё одним популярным ORM — в статье Prisma vs Drizzle.

Насколько безопасна Prisma от SQL-инъекций?

Prisma Client по умолчанию использует параметризованные запросы для всех операций — SQL-инъекции невозможны. При использовании $queryRaw с шаблонными строками также происходит автоматическое экранирование параметров. Опасность возникает только при использовании $queryRawUnsafe — его следует избегать.

Что такое «schema drift» и как Prisma с ним борется?

Schema drift — расхождение между реальной структурой базы данных и описанием в коде. Prisma решает это через систему миграций: каждое изменение схемы фиксируется в файле миграции. Команда prisma migrate status показывает текущее состояние и выявляет дрейф.