Лучшая база данных для Next.js, Node.js и Bun.js в 2026 году

Обновлено:

У выбора базы данных для JavaScript-проекта несколько правильных ответов: PostgreSQL, SQLite, Turso, PocketBase, Neon, Supabase решают разные задачи. Ниже — варианты по сценариям (full-stack Next.js, edge, API-сервер на Node.js или Bun, мультитенантный SaaS, MVP), код подключения и бэкапы перед деплоем.

Почему выбор БД для JS-проектов отличается от других языков

JavaScript (Node.js / Bun.js / Deno) и TypeScript накладывают специфические требования на выбор базы данных:

Edge-окружения: Cloudflare Workers, Vercel Edge Functions, Deno Deploy — это не полноценный Node.js. Обычные TCP-драйверы PostgreSQL там не работают или работают с ограничениями (у Cloudflare для этого есть сокеты и Hyperdrive). Чаще используют драйверы поверх HTTP/WebSocket или edge-native базы.

Serverless: AWS Lambda, Vercel Functions, Netlify Functions легко открывают новое соединение на каждый вызов. Без пула соединений (pgBouncer, Supavisor у Supabase, встроенный пулер Neon) PostgreSQL быстро упирается в max_connections.

TypeScript-first: ORM с полной типизацией — не опция, а стандарт. Drizzle и Prisma дают тип-безопасные запросы без рантайм-ошибок по типу cannot read property of undefined.

Bun.js: встроенный модуль bun:sqlite даёт SQLite без внешних зависимостей, поэтому Bun-проекты часто начинают именно с него.

Выбор ORM: Drizzle или Prisma

Прежде чем обсуждать базы данных, нужно выбрать ORM — прослойку между кодом и БД. Подробное сравнение — в статье Prisma vs Drizzle.

Drizzle ORM — лёгкая ORM с SQL-подобным синтаксисом и описанием схемы на TypeScript:

// drizzle/schema.ts
import { pgTable, text, integer, timestamp, uuid } from 'drizzle-orm/pg-core'

export const users = pgTable('users', {
  id: uuid('id').defaultRandom().primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  createdAt: timestamp('created_at').defaultNow(),
})

export const posts = pgTable('posts', {
  id: uuid('id').defaultRandom().primaryKey(),
  title: text('title').notNull(),
  content: text('content'),
  authorId: uuid('author_id').references(() => users.id),
  publishedAt: timestamp('published_at'),
})
// Типобезопасный запрос с JOIN
const postsWithAuthors = await db
  .select({
    id: posts.id,
    title: posts.title,
    authorName: users.name,
  })
  .from(posts)
  .leftJoin(users, eq(posts.authorId, users.id))
  .where(isNotNull(posts.publishedAt))
  .orderBy(desc(posts.publishedAt))
  .limit(10)

Drizzle поддерживает PostgreSQL, MySQL, SQLite, Turso (LibSQL), Cloudflare D1, Bun SQLite — одна ORM для любого стека.

Prisma — зрелая альтернатива с более удобным синтаксисом для начинающих:

// prisma/schema.prisma
model User {
  id        String   @id @default(cuid())
  name      String
  email     String   @unique
  posts     Post[]
  createdAt DateTime @default(now())
}

model Post {
  id          String    @id @default(cuid())
  title       String
  content     String?
  author      User      @relation(fields: [authorId], references: [id])
  authorId    String
  publishedAt DateTime?
}
// Запрос с include (JOIN)
const posts = await prisma.post.findMany({
  where: { publishedAt: { not: null } },
  include: { author: { select: { name: true } } },
  orderBy: { publishedAt: 'desc' },
  take: 10,
})

Итог: Drizzle — для опытных разработчиков, которые хотят контроль над SQL и edge-совместимость. Prisma — для команд, которые предпочитают декларативную схему и богатую документацию.

Сценарий 1: Next.js App Router + Server Actions (full-stack)

Лучший выбор: PostgreSQL + Drizzle ORM + Neon или Supabase

npm install drizzle-orm @neondatabase/serverless dotenv
npm install -D drizzle-kit
// lib/db.ts — подключение к Neon через serverless driver
import { neon } from '@neondatabase/serverless'
import { drizzle } from 'drizzle-orm/neon-http'
import * as schema from './schema'

const sql = neon(process.env.DATABASE_URL!)
export const db = drizzle(sql, { schema })
// app/actions.ts — Server Action
'use server'
import { db } from '@/lib/db'
import { posts } from '@/lib/schema'
import { revalidatePath } from 'next/cache'

export async function createPost(data: { title: string; content: string }) {
  await db.insert(posts).values({
    title: data.title,
    content: data.content,
    authorId: getCurrentUserId(), // из auth session
  })
  revalidatePath('/blog')
}

Neon — serverless PostgreSQL с драйвером, который ходит в базу по HTTP или WebSocket, поэтому работает и в edge-функциях. Есть бесплатный тариф; лимиты меняются, проверяйте их на сайте провайдера.

Сценарий 2: Next.js + Edge Runtime + Cloudflare Workers

Лучший выбор: Cloudflare D1 + Turso + Drizzle

// lib/db.ts — Turso для edge
import { createClient } from '@libsql/client'
import { drizzle } from 'drizzle-orm/libsql'

const client = createClient({
  url: process.env.TURSO_URL!,
  authToken: process.env.TURSO_AUTH_TOKEN!,
})

export const db = drizzle(client)

Turso (libSQL, форк SQLite) доступен по HTTP, поэтому работает в Cloudflare Workers и Vercel Edge. Подробнее — в статье что такое Turso; актуальные лимиты бесплатного тарифа смотрите на сайте Turso.

Сценарий 3: Node.js / Bun.js API-сервер

Лучший выбор: PostgreSQL + Prisma или Drizzle (для полноценного бэкенда), SQLite + Bun (для минималистичного сервиса)

// Bun.js + встроенный SQLite (нулевые зависимости)
import { Database } from 'bun:sqlite'

const db = new Database('app.db')

// Создание таблицы
db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`)

// Типизированный запрос
const getUser = db.prepare<{ id: number; name: string; email: string }, [number]>(
  'SELECT id, name, email FROM users WHERE id = ?'
)

const user = getUser.get(1)
// Bun.js + Drizzle + SQLite (типобезопасно)
import { drizzle } from 'drizzle-orm/bun-sqlite'
import { Database } from 'bun:sqlite'

const sqlite = new Database('app.db')
const db = drizzle(sqlite)

// Drizzle даёт типизацию поверх bun:sqlite
const users = await db.select().from(usersTable).all()

По бенчмаркам самих разработчиков Bun, bun:sqlite быстрее better-sqlite3; на ваших запросах разница может быть другой, так что меряйте сами.

Сценарий 4: SaaS с мультитенантностью

Лучший выбор: PostgreSQL + Drizzle + Row-Level Security или Turso (одна БД на тенанта)

Паттерн «одна БД на тенанта» с Turso:

// Для каждого нового клиента — отдельная база (Turso Platform API)
import { createClient } from '@tursodatabase/api'

const turso = createClient({
  org: process.env.TURSO_ORG!,
  token: process.env.TURSO_API_TOKEN!,
})

async function createTenantDb(tenantId: string) {
  const db = await turso.databases.create(`tenant-${tenantId}`, { group: 'default' })
  return db.hostname // хост для подключения клиента
}

Сигнатуры Platform API сверяйте с документацией Turso. Помните, что при модели «база на клиента» бэкапы и миграции нужно выполнять для каждой базы отдельно.

Сценарий 5: Indie-проект / MVP

Лучший выбор: PocketBase (SQLite внутри)

PocketBase даёт базу данных, авторизацию, файловое хранилище и REST API без написания бэкенда (подробнее — что такое PocketBase). Одна команда:

./pocketbase serve

Подключение к Next.js:

// lib/pocketbase.ts
import PocketBase from 'pocketbase'

// Singleton для клиентской стороны
const pb = new PocketBase(process.env.NEXT_PUBLIC_PB_URL!)
export default pb
// Server Component в Next.js
import PocketBase from 'pocketbase'

async function getPosts() {
  // Серверная сторона — новый экземпляр без persistence
  const pb = new PocketBase(process.env.PB_URL!)
  return pb.collection('posts').getList(1, 20, {
    filter: 'published = true',
    sort: '-created',
  })
}

Сравнительная таблица баз данных для JS

Оценки субъективные и отражают удобство в типичном проекте, а не производительность.

| База данных | Next.js | Node.js | Bun.js | Edge | Serverless | Как платите | |---|---|---|---|---|---|---| | PostgreSQL (self-hosted) | ★★★★★ | ★★★★★ | ★★★★★ | ✗ | ⚠️ (нужен пул) | VPS | | Neon (managed PG) | ★★★★★ | ★★★★☆ | ★★★★☆ | ★★★★★ | ★★★★★ | Есть бесплатный тариф | | Supabase | ★★★★★ | ★★★★★ | ★★★★☆ | ⚠️ | ★★★★☆ | Есть бесплатный тариф | | SQLite (local/Bun) | ★★★☆☆ | ★★★★☆ | ★★★★★ | ✗ | ✗ | Бесплатно, нужен диск | | Turso (libSQL) | ★★★★★ | ★★★★★ | ★★★★★ | ★★★★★ | ★★★★★ | Есть бесплатный тариф | | PocketBase | ★★★★★ | ★★★★☆ | ★★★☆☆ | ✗ | ✗ | VPS | | Cloudflare D1 | ★★★★☆ (на Workers) | ✗ | ✗ | ★★★★★ | ★★★★★ | Есть бесплатный тариф | | MongoDB Atlas | ★★★★☆ | ★★★★★ | ★★★★☆ | ⚠️ | ★★★★☆ | Есть бесплатный кластер |

Лимиты бесплатных тарифов у облачных сервисов меняются — проверяйте их на сайтах провайдеров.

Рекомендации по стеку

Стандартный full-stack Next.js проект: PostgreSQL (Neon) + Drizzle ORM + Next.js App Router + Server Actions

Edge-first приложение: Turso + Drizzle + Cloudflare Workers / Vercel Edge

Быстрый MVP или indiehacker: PocketBase + Next.js (без написания бэкенда)

Bun.js микросервис: bun:sqlite + Drizzle или чистый SQL через bun:sqlite

SaaS с мультитенантностью: Turso (одна БД на тенанта) или PostgreSQL + RLS через Supabase

Высокая нагрузка, российские данные: PostgreSQL на Яндекс Cloud Managed PostgreSQL + pgBouncer

Бэкапы БД в JavaScript-проектах

Какую бы базу вы ни выбрали, копия должна жить отдельно от сервера приложения. Для managed-сервисов (Neon, Supabase, Turso) проверьте, что входит во встроенные бэкапы на вашем тарифе и сколько они хранятся. Для self-hosted PostgreSQL и SQLite бэкап — ваша задача.

Удобная точка — шаг CI/CD перед миграциями. Для SQLite-файла (Bun, PocketBase, better-sqlite3) CLI dbsend сам делает консистентную копию работающей базы, для PostgreSQL дамп делаете вы:

npm install --global @dbsend/sdk   # нужен Node.js 22.12+

# SQLite: версия с меткой коммита
dbsend backup ./data/app.db -d "$DBSEND_DATABASE_ID" -e sqlite -l "deploy-${GITHUB_SHA:-local}"

# PostgreSQL (self-hosted, Neon, Supabase): plain-дамп + загрузка
pg_dump --format=plain --no-owner "$DATABASE_URL" > /tmp/app.sql
dbsend backup /tmp/app.sql -d "$DBSEND_PG_DATABASE_ID" -e postgresql_dump -l "deploy-${GITHUB_SHA:-local}"

Ключ передаётся через переменную DBSEND_API_KEY (секрет CI), ID базы — через DBSEND_DATABASE_ID или файл .dbsend.json после dbsend init. Если файл не изменился с прошлой загрузки, новая версия не создаётся. Все команды — в документации CLI.

Если копируете SQLite сами, не используйте cp на работающей базе в WAL-режиме — см. как сделать бэкап SQLite без повреждения. Для PostgreSQL по расписанию — pg_dump по cron в S3. Подробнее о версиях и сравнении SQLite-баз — на странице бэкапы SQLite.

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

Что лучше для Next.js: Prisma или Drizzle?

Зависит от команды. Drizzle ближе к SQL, легче, без генерации клиента и хорошо работает в edge-окружениях. Prisma даёт декларативную схему, развитые миграции, подробную документацию и поддержку MongoDB. Для новых edge- и serverless-проектов чаще выбирают Drizzle, для команд, которым важна декларативная схема, — Prisma.

Работает ли Prisma с Bun?

Да, Prisma работает в Bun-проектах. Нативный драйвер bun:sqlite поддерживает Drizzle; для Prisma с SQLite в Bun проверьте актуальную поддержку драйверных адаптеров в документации Prisma. С PostgreSQL и MySQL в Bun работают обе ORM.

Можно ли использовать PostgreSQL с Vercel Edge Functions?

Обычный TCP-драйвер pg в Edge Runtime не работает. Нужен драйвер поверх HTTP/WebSocket, например @neondatabase/serverless, или REST API Supabase. Turso тоже работает на edge через HTTP. Во многих случаях проще выполнять запросы к PostgreSQL в обычных Server Components и Route Handlers на Node.js runtime.

Что такое serverless PostgreSQL и зачем он нужен?

В serverless-окружении функции запускаются и останавливаются по запросам, и каждая может открыть своё соединение — база быстро упирается в лимит соединений. Serverless PostgreSQL (Neon, Supabase) решает это пулером соединений и драйверами поверх HTTP/WebSocket.

Какую базу выбрать для хакатона на Next.js?

Supabase — быстрый старт: панель, REST API и авторизация из коробки. Neon + Drizzle — если нужен контроль на TypeScript. PocketBase на VPS — если хотите обойтись без написания бэкенда.