Настройка PostgreSQL в Node.js с помощью Sequelize
Краткий план: подключите PostgreSQL к Node.js через Sequelize, настройте соединение через URI или параметры, опишите модели через DataTypes и выполняйте CRUD через методы ORM. В статье есть практические примеры, конфигурация для разработки и развёртывания, чек-листы, рекомендации по безопасности и советы по отладке.

Sequelize — это ORM для Node.js, который предоставляет удобный API для реляционных баз данных, таких как PostgreSQL, MySQL, MariaDB, SQLite и другие. PostgreSQL — широко используемая открытая СУБД с богатым набором возможностей, хорошей безопасностью и масштабируемостью. В этой статье пошагово показано, как настроить PostgreSQL в проекте Node.js с помощью Sequelize, как определять модели, выполнять запросы и какие практики применять в продакшне.
О чём этот материал
- как установить зависимости и драйверы
- как подключиться к базе через URI или параметры
- как описать модель и синхронизировать таблицу
- примеры CRUD-операций через Sequelize
- дополнительные рекомендации: безопасность, бэкапы, миграции, Docker, чек-листы
Шаг 1: установка зависимостей
Перед подключением к PostgreSQL нужно установить саму СУБД локально или использовать облачный сервис вроде ElephantSQL. Для локальной установки перейдите на официальный сайт PostgreSQL и скачайте дистрибутив для своей ОС. На macOS полезно использовать Homebrew: brew install postgresql
Альтернатива локальной установке — развёртывание контейнера PostgreSQL через Docker или использование управляемого сервиса.
Далее установите sequelize и драйвер для PostgreSQL в проект Node.js:
npm install sequelize
npm install pg pg-hstore
pg — официальный драйвер для PostgreSQL. pg-hstore нужен для сериализации типов hstore, если вы планируете их использовать.
Важные заметки:
- держите версии sequelize и pg совместимыми по релизам
- для TypeScript-проектов дополнительно устанавливайте типы и используйте sequelize-typescript или типовые объявления
Шаг 2: подключение к базе данных PostgreSQL
Создайте каталог конфигурации, например config, и файл db.js внутри него. В этом файле задаётся экземпляр Sequelize и функция тестирования соединения.
Пример простого файла config/db.js:
const { Sequelize } = require('sequelize')
// пример с параметрами подключения
const sequelize = new Sequelize('database', 'username', 'password')
// или используя URI из переменных окружения
// const sequelize = new Sequelize(process.env.POSTGRESQL_DB_URI)
const testDbConnection = async () => {
try {
await sequelize.authenticate()
console.log('Соединение успешно установлено.')
} catch (error) {
console.error('Не удалось подключиться к базе данных:', error)
}
}
module.exports = { sq: sequelize, testDbConnection }
Пояснения:
- конструктор Sequelize принимает параметры: имя базы, пользователя, пароль, а также опционально объект с настройками
- альтернативный способ — один строковый URI вида postgres://user:pass@host:port/dbname
- метод authenticate() проверяет соединение без выполнения миграций
Рекомендации по конфигурации:
- храните чувствительные данные в переменных окружения, а не в коде
- в dev-режиме используйте .env и пакет dotenv, в продакшне — секреты платформы
Пример .env и использования в db.js:
// .env
POSTGRESQL_DB_URI=postgres://user:password@localhost:5432/mydb
// config/db.js
require('dotenv').config()
const { Sequelize } = require('sequelize')
const sequelize = new Sequelize(process.env.POSTGRESQL_DB_URI)
module.exports = { sq: sequelize }
Шаг 3: создание модели Sequelize
Создайте папку models и в ней файлы моделей. Название файла должно отражать сущность, например user.js или product.js.
Пример модели models/user.js:
const { sq } = require('../config/db')
const { DataTypes } = require('sequelize')
const User = sq.define('user', {
email: {
type: DataTypes.STRING,
allowNull: false,
primaryKey: true,
},
fullName: {
type: DataTypes.STRING,
},
age: {
type: DataTypes.INTEGER,
},
employed: {
type: DataTypes.BOOLEAN,
defaultValue: false,
},
})
User.sync().then(() => {
console.log('User модель синхронизирована')
})
module.exports = User
Пояснения по свойствам:
- DataTypes задаёт типы столбцов
- allowNull: false эквивалент NOT NULL
- primaryKey: true делает поле первичным ключом
- defaultValue задаёт значение по умолчанию
Метод sync имеет несколько режимов работы:
- Model.sync() — создать таблицу, если её нет
- Model.sync({ force: true }) — удалить таблицу и создать заново (опасно в проде)
- Model.sync({ alter: true }) — попытаться привести таблицу в соответствие с моделью
В большинстве проектов в продакшне используют миграции вместо sync с force/alter, чтобы не потерять данные и иметь контроль версий схемы.
CRUD: создание, чтение, обновление, удаление
Все примеры ниже предполагают, что модель User импортирована и подключение уже инициализировано.
Сохранение данных:
const mike = await User.create({
email: 'mike@example.com',
fullName: 'Mike Smith',
age: 30,
employed: true,
})
Получение данных:
// найти всех пользователей
const users = await User.findAll()
// найти одного пользователя по условию
const mike = await User.findOne({ where: { email: 'mike@example.com' } })
Фильтрация через where:
const unemployed = await User.findAll({
where: {
employed: false,
},
})
Обновление данных:
// массовое обновление
await User.update({ employed: true }, {
where: {
employed: false,
},
})
// обновление через экземпляр
const userMike = await User.findOne({ where: { email: 'mike@example.com' } })
if (userMike !== null) {
userMike.email = 'mike@example.org'
await userMike.save()
}
Удаление данных:
await User.destroy({
where: {
email: 'mike@example.org',
},
})
Важно: методы update и destroy применяются к записям, которые удовлетворяют условию where. Будьте осторожны с пустыми where, чтобы не удалить все записи.
Конфигурация для разработки: Docker и локальный Postgres
Пример docker-compose.yml для локальной разработки:
version: '3.8'
services:
db:
image: postgres:14
restart: always
environment:
POSTGRES_USER: devuser
POSTGRES_PASSWORD: devpass
POSTGRES_DB: devdb
ports:
- '5432:5432'
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
После запуска docker compose up -d база будет доступна на localhost:5432 и вы сможете указать в .env URI postgres://devuser:devpass@localhost:5432/devdb
Использование управляемых сервисов: пример ElephantSQL
Если вы используете ElephantSQL или аналогичный провайдер, в панели управления вы получите строку подключения вида postgres://user:password@host:port/dbname
Используйте её в переменной окружения POSTGRESQL_DB_URI и подключайтесь в коде через new Sequelize(process.env.POSTGRESQL_DB_URI)
Миграции и контроль схемы
Для контроля версий схемы рекомендуется использовать систему миграций, например umzug вместе с sequelize-cli или сторонние инструменты. Миграции позволяют:
- применять изменения шаг за шагом
- откатывать изменения при ошибках
- управлять схемой в командах разработки и CI/CD
Примерный рабочий процесс миграций:
- создать миграцию, описать ALTER/CREATE TABLE
- запустить миграции в staging и тестовой среде
- прогнать тесты и проверки целостности
- выполнить миграции в продакшне по окну обслуживания
Безопасность и жёсткое производство
Рекомендации по защите данных и соединения:
- используйте SSL/TLS для соединений к базе в продакшне
- применяйте принцип наименьших привилегий: отдельный пользователь для приложения с ограниченным набором прав
- храните секреты в менеджере секретов или переменных окружения, не в репозитории
- выполняйте регулярные бэкапы базы и проверяйте процедуры восстановления
- логируйте и мониторьте медленные запросы и ошибки соединений
- избегайте использования sync({ force: true }) в автоматических релизах
Когда Sequelize может не подойти
- вам нужны сложные специфичные SQL-возможности, которые тяжело выразить через ORM
- вы стремитесь к максимальной производительности в критичных местах, где ORM добавляет накладные расходы
- коллектив предпочитает строго типизированные схемы и миграции на уровне TypeScript, тогда Prisma и титановые инструменты могут быть предпочтительнее
В таких случаях рассмотрите альтернативы: Prisma, TypeORM, Objection.js, Knex.js (query builder)
Альтернативные подходы
- Prisma: современный ORM с генерацией типов для TypeScript, хорош для проектов с сильной статической типизацией
- TypeORM: ORM с похожим API на Active Record / Data Mapper
- Objection.js + Knex: ORM над query builder, удобен если нужен контроль SQL и гибкость
- Чистый SQL через pg или query builder: для высокопроизводительных участков и простоты
Ментальные модели и эвристики
- модели = проекция объектов приложения на таблицы/строки базы данных
- миграции = скоординированные изменения схемы, которые должны быть идемпотентными и обратимыми
- синхронизация в dev != миграции в prod
- ORM упрощает CRUD, но не заменяет понимание SQL и индексов
Чек-листы
Для разработчика перед деплоем:
- проверено ли подключение через переменные окружения
- нет ли в коде sync({ force: true }) или других опасных вызовов
- есть ли миграции для всех изменений схемы
- настроены ли бэкапы и мониторинг
Для DevOps:
- настроены ли секреты и SSL
- проверены ли права пользователя БД
- есть ли план восстановления и точные инструкции
- прогнаны ли миграции в staging
Быстрый справочник и сниппеты
Подключение через URI:
const sequelize = new Sequelize(process.env.POSTGRESQL_DB_URI)
Запрос с сортировкой и лимитом:
const recentUsers = await User.findAll({
where: { employed: true },
order: [['createdAt', 'DESC']],
limit: 10,
})
Транзакция:
const result = await sq.transaction(async t => {
const a = await ModelA.create({ /*...*/ }, { transaction: t })
const b = await ModelB.update({ /*...*/ }, { where: { id: a.id }, transaction: t })
return { a, b }
})
Индексы и уникальные ограничения определяются в модели через параметры индексов или уникальные поля.
Рекомендации по тестированию и критериям приёмки
Критерии приёмки для базовой интеграции:
- приложение устанавливает соединение с базой и authenticate() возвращает без ошибок
- базовая модель создала таблицу и CRUD-операции работают в тестовой среде
- миграции применяются и откатываются в тестовом окружении
- мониторинг фиксирует количество подключений и ошибки
Тестовые кейсы:
- создать, прочитать, обновить, удалить запись через API
- проверить обработку ошибок при недоступности базы
- протестировать откат транзакции при ошибке
План действий при инциденте и откате
Если миграция привела к потере данных или нарушению функционала:
- срочно переключить трафик на статическое резервное окружение или предыдущий релиз
- восстановить бэкап базы в тестовой среде и провести анализ
- откатить проблемную миграцию при помощи инструментов миграций
- ввести режим обслуживания при необходимости и уведомить заинтересованные стороны
Важно: заранее тестировать процедуры восстановления и отката на регулярной основе.
Частые ошибки и отладка
- ошибка аутентификации: проверьте переменные окружения и сетевой доступ
- конфликт версий pg и sequelize: сверяйте совместимость в changelog
- потеря данных после sync({ force: true }): избегайте в проде, используйте бэкапы
- медленные запросы: добавьте индексы, оптимизируйте запросы, профилируйте через pg_stat_statements
Заключение
Sequelize упрощает работу с PostgreSQL, позволяя работать на уровне моделей и методов без нужно писать SQL вручную. Для продакшна рекомендуются миграции, управление секретами, SSL-соединения и регулярные бэкапы. Если проект требует строгой типизации или высокой производительности, стоит сравнить Sequelize с альтернативами.
В этой статье были приведены примеры подключения, создания моделей и основных операций CRUD, а также дополнительные рекомендации по безопасности, разработке через Docker и обработке инцидентов.
Важно: начните с простых моделей и постепенно вводите миграции и мониторинг, чтобы обеспечить стабильность и предсказуемость работы приложения.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone