Подключение Node.js к PostgreSQL с помощью node-postgres

- Покажу, как быстро подключить Node.js-приложение к PostgreSQL с помощью пакета node-postgres (pg).
- Разберём два подхода: одиночный клиент (Client) и пул соединений (Pool), развернём .env, добавим базовые практики безопасности и чек-листы для разработки и продакшена.
Зачем это нужно
Практически любое приложение работает с хранилищем данных. PostgreSQL — популярная реляционная СУБД: устойчивый выбор для сложных схем, транзакций и аналитики. Пакет node-postgres (pg) — стандартный клиент для Node.js, который позволяет выполнять SQL-запросы и управлять соединениями.
Важно понимать 2 модели доступа:
- Одиночный клиент — один постоянный TCP/PG-соединение; подходит для простых скриптов или утилит.
- Пул соединений — набор переиспользуемых соединений; нужен для веб-приложений с параллельными запросами.
Требования и подготовка
- Установлен PostgreSQL-сервер (локально или доступен удалённо).
- Установлен Node.js (рекомендуется версия 14+).
- Доступ к терминалу и возможность устанавливать npm-пакеты.
Краткое объяснение терминов:
- Пул соединений — менеджер, который держит несколько открытых соединений к базе и раздаёт их по запросам.
- .env — файл с переменными окружения, который не должен попадать в систему контроля версий.
Создание проекта Node
Откройте терминал и создайте папку проекта:
mkdir postgres-nodeПерейдите в папку и инициализируйте npm:
cd postgres-node
npm init -yСоздайте файл index.js — в нём будут примеры подключения.
Установка node-postgres
Установите пакет pg:
npm install pgЕсли у вас Node >= 14.x и вам нужна конкретная версия, укажите её:
npm install pg@8.7.3Также установите dotenv для загрузки переменных окружения из файла .env:
npm install dotenvПеременные окружения
Создайте файл .env в корне проекта и добавьте параметры подключения, заменив значения на реальные:
PGUSER=
PGHOST=
PGPASSWORD=
PGDATABASE=
PGPORT= В index.js подключите dotenv:
const dotenv = require("dotenv")
dotenv.config()Подключение с одиночным клиентом
Используйте Client, если нужен один статический коннект (например, скрипт миграции):
const { Client } = require("pg")
const dotenv = require("dotenv")
dotenv.config()
const connectDb = async () => {
try {
const client = new Client({
user: process.env.PGUSER,
host: process.env.PGHOST,
database: process.env.PGDATABASE,
password: process.env.PGPASSWORD,
port: process.env.PGPORT
})
await client.connect()
const res = await client.query('SELECT * FROM some_table')
console.log(res)
await client.end()
} catch (error) {
console.log(error)
}
}
connectDb()Когда использовать:
- Скрипты миграции, одноразовые задачи, утилиты.
Ограничения:
- Одно соединение — узкое место при параллельных запросах.
Подключение с пулом соединений
Пул предпочтителен для веб-сервисов и приложений с параллелизмом:
const { Pool } = require("pg")
const dotenv = require("dotenv")
dotenv.config()
const connectDb = async () => {
try {
const pool = new Pool({
user: process.env.PGUSER,
host: process.env.PGHOST,
database: process.env.PGDATABASE,
password: process.env.PGPASSWORD,
port: process.env.PGPORT,
});
await pool.connect()
const res = await pool.query('SELECT * FROM clients')
console.log(res)
await pool.end()
} catch (error) {
console.log(error)
}
}
connectDb()Советы по пулу:
- Не создавайте новый пул на каждый HTTP-запрос — создавайте пул один раз при старте приложения и реиспользуйте.
- Корректно возвращайте соединения в пул (при ручном взятии через pool.connect() вызывайте release()).
Использование стандартных переменных окружения
Вы можете не передавать объект конфигурации в Pool/Client и опираться на переменные окружения:
const connectDb = async () => {
try {
const pool = new Pool();
const res = await pool.query('SELECT * FROM clients')
console.log(res)
await pool.end()
} catch (error) {
console.log(error)
}
}
Запуск с передачей переменных в окружении:
PGUSER= \
PGHOST= \
PGPASSWORD= \
PGDATABASE= \
PGPORT= \
node index.js Это удобно в CI/CD и при деплое, когда настройки задаются на стороне окружения.
Безопасность и практики для продакшена
- Не храните секреты в репозитории. .env должен быть в .gitignore.
- Используйте защищённое соединение (SSL/TLS), если база доступна по сети: в конфиг передайте ssl: { rejectUnauthorized: true } или используйте connection string с параметром sslmode.
- Минимизируйте права пользователя базы: давайте отдельного пользователя для приложения с необходимыми правами.
- Логируйте ошибки, но не раскрывайте пароли в логах.
Пример добавления SSL в конфиг пула:
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
ssl: {
rejectUnauthorized: false
}
});Примечание: поведение ssl зависит от хостинга и сертификатов; настройте rejectUnauthorized по требованиям безопасности.
Отладка и распространённые ошибки
- ECONNREFUSED — сервер недоступен или порт неправильный.
- 3D000 — база данных не найдена (PGDATABASE неверна).
- 28P01 — ошибка аутентификации (проверьте логин/пароль).
- «too many clients» — пул переполнен; уменьшите параллелизм или увеличьте размер пула.
Полезные команды для проверки соединения:
- psql -h
-U -d — проверка доступа из терминала.
Настройка размеров пула и эвристики
- Для приложений с низкой нагрузкой достаточно 5–10 соединений.
- Для высоконагруженных сервисов ориентируйтесь на количество CPU и количество одновременных запросов, но избегайте открытия сотен соединений — PostgreSQL потребляет память на каждое.
- Альтернатива — использовать connection pooling на уровне сервера (PgBouncer) для масштабирования.
Чек-лист перед деплоем
- Секреты хранятся в защищённом хранилище (Vault/Secrets manager).
- .env отсутствует в репозитории.
- SSL настроен для удалённых баз.
- Пулы созданы один раз при старте приложения.
- Таймауты и ретраи настроены для критичных запросов.
- Мониторинг подключений и метрик настроен (количество активных соединений, время отклика).
Инцидентный план и откат
- Выявление: метрики показывают рост ожиданий соединений и ошибок.
- Митигирование: уменьшите входящий трафик (фич-флаг, снять очередные задания), перезапустите приложение для освобождения зависших соединений.
- Откат: если развертывание нового релиза вызвало утечку соединений — откатите до предыдущей версии.
- Коррекция: убедитесь, что пул создаётся единожды и что используется корректная обработка ошибок и release() для соединений.
Когда node-postgres не подходит и альтернативы
- Если требуется масштабирование на уровне десятков тысяч коротких соединений, рассмотрите PgBouncer как прокси-пул.
- Для распределённых NoSQL-наборов данных — MongoDB, Redis и т.п.
- Для упрощения доступа и типобезопасного кода — использование ORM (TypeORM, Prisma) может быть удобнее, но они добавляют уровень абстракции.
Шаблон тест-кейса для проверки подключения
- Подключение с корректными переменными окружения возвращает успешный результат и строки.
- Некорректный пароль возвращает ошибку аутентификации.
- При недоступности сервера приложение корректно логирует и не падает неконтролируемо.
- Пул не создаёт больше N соединений при N одновременных запросах.
Короткий глоссарий
- Pool — пул соединений, переиспользуемые подключения к базе.
- Client — одиночное подключение к базе.
- .env — файл с переменными окружения.
Критерии приёмки
- Приложение успешно выполняет тестовый SELECT и получает ожидаемые строки.
- При запуске в продакшене состояние пулов и активных соединений в допустимых пределах.
- Отсутствие секретов в публичном репозитории.
Итог
Подключение Node.js к PostgreSQL с помощью node-postgres — задача из разряда базовых, но требующая внимания к моделям подключения, безопасности и управлению пулом. Для простых сценариев подойдёт Client, для веб-приложений — Pool. В продакшене используйте безопасные секреты, SSL и мониторинг соединений.
Важно
- Всегда тестируйте конфигурацию в окружении, близком к продакшену.
- При росте нагрузки подумайте о PgBouncer и стратегиях кэширования.